From: John Hodge Date: Sun, 5 Aug 2012 11:02:35 +0000 (+0800) Subject: Merge branch 'master' of git.mutabah.net:acess2 X-Git-Tag: rel0.15~706^2~70^2 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=8dcc3e209d0d728565a18c8dca2b0ba220b74a6f;hp=e02f66c7125bf18f77c6c53587238cbd49da2c89;p=tpg%2Facess2.git Merge branch 'master' of git.mutabah.net:acess2 Conflicts: KernelLand/Modules/IPStack/adapters.c --- diff --git a/BuildConf/armv6/Makefile.cfg b/BuildConf/armv6/Makefile.cfg new file mode 100644 index 00000000..00ed8895 --- /dev/null +++ b/BuildConf/armv6/Makefile.cfg @@ -0,0 +1,18 @@ + +ARM_CPUNAME = gerneric-armv6 +CC = arm-armv6-eabi-gcc -mcpu=$(ARM_CPUNAME) +AS = arm-armv6-eabi-gcc -mcpu=$(ARM_CPUNAME) -c +LD = arm-armv6-eabi-ld +OBJDUMP = arm-armv6-eabi-objdump +DISASM = $(OBJDUMP) -d -S +ARCHDIR = armv6 +STRIP = arm-elf-strip + +ASSUFFIX = S + +# Default Configuration +ifeq ($(PLATFORM),) + PLATFORM=raspberrypi +$(warning Defaulting to "PLATFORM=$(PLATFORM)") +endif + diff --git a/BuildConf/armv6/default.mk b/BuildConf/armv6/default.mk new file mode 100644 index 00000000..3b3cc8ba --- /dev/null +++ b/BuildConf/armv6/default.mk @@ -0,0 +1,7 @@ + +ifeq ($(PLATFORM),default) + $(error Please select a platform) +endif + +#MODULES += armv7/GIC +MODULES += Filesystems/InitRD diff --git a/BuildConf/armv6/raspberrypi.mk b/BuildConf/armv6/raspberrypi.mk new file mode 100644 index 00000000..01f08df2 --- /dev/null +++ b/BuildConf/armv6/raspberrypi.mk @@ -0,0 +1,3 @@ + +include $(ACESSDIR)/BuildConf/armv6/default.mk +ARM_CPUNAME = arm1176jzf-s diff --git a/KernelLand/Kernel/Makefile b/KernelLand/Kernel/Makefile index 1c7cb637..66eb9cdd 100644 --- a/KernelLand/Kernel/Makefile +++ b/KernelLand/Kernel/Makefile @@ -100,7 +100,7 @@ apidoc: # - Does whatever architecture defined rules $(BIN): $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile ../../BuildConf/$(ARCH)/Makefile.cfg ../../BuildConf/$(ARCH)/$(PLATFORM).mk @echo --- LD -o $(BIN) - @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) --defsym __buildnum=$$(( $(BUILD_NUM) + 1 )) -Map ../Map.$(ARCH).txt + @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) $(LIBGCC_PATH) --defsym __buildnum=$$(( $(BUILD_NUM) + 1 )) -Map ../Map.$(ARCH).txt @$(DISASM) -S $(BIN) > $(BIN).dsm @echo BUILD_NUM = $$(( $(BUILD_NUM) + 1 )) > Makefile.BuildNum.$(ARCH) $(POSTBUILD) diff --git a/KernelLand/Kernel/arch/armv6/Makefile b/KernelLand/Kernel/arch/armv6/Makefile new file mode 100644 index 00000000..b6768e30 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/Makefile @@ -0,0 +1,21 @@ +# +# Acess2 Kernel +# arm7 Architecture Makefile +# arch/arm7/Makefile + +CPPFLAGS = +CFLAGS = +ASFLAGS = + +CPPFLAGS += -DMMU_PRESENT=1 +LDFLAGS += +LIBGCC_PATH = $(shell $(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 + +#main.c: Makefile.BuildNum.$(ARCH) + +ifeq ($(PLATFORM),tegra2) + POSTBUILD = arm-elf-objcopy $(BIN) -O binary $(BIN) +endif diff --git a/KernelLand/Kernel/arch/armv6/debug.c b/KernelLand/Kernel/arch/armv6/debug.c new file mode 100644 index 00000000..7b9e55dd --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/debug.c @@ -0,0 +1,57 @@ +/** + * Acess2 + * - By John Hodge (thePowersGang) + * + * arch/arm7/debug.c + * - ARM7 Debug output + * NOTE: Currently designed for the realview-pb-a8 emulated by Qemu + */ +#include + +// === CONSTANTS === +//#define UART0_BASE 0x10009000 +#define UART0_BASE 0xF1000000 // Boot time mapped + +// === PROTOTYPES === +void KernelPanic_SetMode(void); +void KernelPanic_PutChar(char Ch); +void StartupPrint(const char *str); + +// === GLOBALS === + int giDebug_SerialInitialised = 0; + +// === CODE === +void Debug_PutCharDebug(char ch) +{ + if(ch == '\n') + Debug_PutCharDebug('\r'); + + #if PLATFORM_is_tegra2 + // Tegra2 + while( !(*(volatile Uint32*)(UART0_BASE + 0x14) & (1 << 5)) ) + ; + #endif + +// *(volatile Uint32*)(SERIAL_BASE + SERIAL_REG_DATA) = ch; + *(volatile Uint32*)(UART0_BASE) = ch; +} + +void Debug_PutStringDebug(const char *str) +{ + for( ; *str; str++ ) + Debug_PutCharDebug( *str ); +} + +void KernelPanic_SetMode(void) +{ +} + +void KernelPanic_PutChar(char ch) +{ +// Debug_PutCharDebug(ch); +} + +void StartupPrint(const char *str) +{ +} + diff --git a/KernelLand/Kernel/arch/armv6/include/arch.h b/KernelLand/Kernel/arch/armv6/include/arch.h new file mode 100644 index 00000000..837a5e10 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/include/arch.h @@ -0,0 +1,44 @@ +/* + * Acess2 + * ARM7 Architecture Header + */ +#ifndef _ARCH_H_ +#define _ARCH_H_ + +// === CONSTANTS === +#define INVLPTR ((void*)-1) +#define BITS 32 +#define PAGE_SIZE 0x1000 +#define KERNEL_BASE 0x80000000 // 2GiB + +// === TYPES === +typedef unsigned int Uint; +typedef unsigned char Uint8; +typedef unsigned short Uint16; +typedef unsigned long Uint32; +typedef unsigned long long Uint64; +typedef signed int Sint; +typedef signed char Sint8; +typedef signed short Sint16; +typedef signed long Sint32; +typedef signed long long Sint64; + +typedef int size_t; +typedef char BOOL; + +typedef Uint32 tVAddr; +typedef Uint32 tPAddr; + +#include "lock.h" + +// --- Debug +extern void Debug_PutCharDebug(char Ch); +extern void Debug_PutStringDebug(const char *String); + +// This should be elsewhere, but CBF +extern void MM_SetupPhys(void); +extern int MM_InitialiseVirtual(void); + +#define NO_IO_BUS 1 + +#endif diff --git a/KernelLand/Kernel/arch/armv6/include/assembly.h b/KernelLand/Kernel/arch/armv6/include/assembly.h new file mode 100644 index 00000000..0c5c57fb --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/include/assembly.h @@ -0,0 +1,46 @@ +/* + * Acess2 ARMv7 + * - By John Hodge (thePowersGang) + * + * arch/arm7/include/assembly.h + * - Assembly specific macros + */ +#ifndef _ASSEMBLY_H_ +#define _ASSEMBLY_H_ + +#define PUSH_GPRS \ + str r0, [sp,#-1*4];\ + str r1, [sp,#-2*4];\ + str r2, [sp,#-3*4];\ + str r3, [sp,#-4*4];\ + str r4, [sp,#-5*4];\ + str r5, [sp,#-6*4];\ + str r6, [sp,#-7*4];\ + str r7, [sp,#-8*4];\ + str r8, [sp,#-9*4];\ + str r9, [sp,#-10*4];\ + str r10, [sp,#-11*4];\ + str r11, [sp,#-12*4];\ + str r12, [sp,#-13*4];\ + str sp, [sp,#-14*4];\ + str lr, [sp,#-15*4];\ + sub sp, #16*4 + +#define POP_GPRS add sp, #16*4; \ + ldr r0, [sp,#-1*4]; \ + ldr r1, [sp,#-2*4]; \ + ldr r2, [sp,#-3*4]; \ + ldr r3, [sp,#-4*4]; \ + ldr r4, [sp,#-5*4]; \ + ldr r5, [sp,#-6*4]; \ + ldr r6, [sp,#-7*4]; \ + ldr r7, [sp,#-8*4]; \ + ldr r8, [sp,#-9*4]; \ + ldr r9, [sp,#-10*4]; \ + ldr r10, [sp,#-11*4]; \ + ldr r11, [sp,#-12*4]; \ + ldr r12, [sp,#-13*4]; \ + ldr lr, [sp,#-15*4]; + +#endif + diff --git a/KernelLand/Kernel/arch/armv6/include/lock.h b/KernelLand/Kernel/arch/armv6/include/lock.h new file mode 100644 index 00000000..6688af48 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/include/lock.h @@ -0,0 +1,63 @@ +/* + * Acess2 + * ARM7 Architecture + * + * lock.h - Hardware level spinlocks + */ +#ifndef _LOCK_H_ +#define _LOCK_H_ + +// === CODE === +struct sShortSpinlock { + int Lock; +}; + +// --- Spinlocks --- +static inline int IS_LOCKED(struct sShortSpinlock *Lock) +{ + return !!Lock->Lock; +} + +static inline int CPU_HAS_LOCK(struct sShortSpinlock *Lock) +{ + // TODO: Handle multiple CPUs + return !!Lock->Lock; +} + +static inline int SHORTLOCK(struct sShortSpinlock *Lock) +{ + #if 0 + // Coped from linux, yes, but I know what it does now :) + Uint tmp; + __asm__ __volatile__ ( + "1: ldrex %0, [%1]\n" // Exclusive LOAD + " teq %0, #0\n" // Check if zero + " strexeq %0, %2, [%1]\n" // Set to one if it is zero (releasing lock on the memory) + " teqeq %0, #0\n" // If the lock was avaliable, check if the write succeeded + " bne 1b" // If the lock was unavaliable, or the write failed, loop + : "=&r" (tmp) // Temp + : "r" (&Lock->Lock), "r" (1) + : "cc" // Condition codes clobbered + ); + #elif 1 + while( *(volatile int*)&Lock->Lock ) ; + Lock->Lock = 1; + #else + int v = 1; + while( v ) + __asm__ __volatile__ ( + "swp %0, %0, [%1]" + : "=r" (v) : "r" (&Lock->Lock) + : "cc" + ); + #endif + return 1; +} + +static inline void SHORTREL(struct sShortSpinlock *Lock) +{ + Lock->Lock = 0; +} + +#endif + diff --git a/KernelLand/Kernel/arch/armv6/include/mm_virt.h b/KernelLand/Kernel/arch/armv6/include/mm_virt.h new file mode 100644 index 00000000..c1f10deb --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/include/mm_virt.h @@ -0,0 +1,57 @@ +/* + * Acess2 + * ARM7 Virtual Memory Manager Header + */ +#ifndef _MM_VIRT_H_ +#define _MM_VIRT_H_ + +#include "options.h" + +#define USER_STACK_COMM 0x04000 // Pages to allocate up front +#define USER_STACK_SIZE 0x10000 // Stack space +#define USER_STACK_TOP 0x78000000 + +#define MM_USER_MIN 0x00001000 +#define USER_LIB_MAX 0x70000000 +#define MM_PPD_HANDLES 0x7F800000 +#define MM_TABLE1USER 0x7FC00000 // 2 GiB - 4 MiB +#define MM_TABLE0USER 0x7FE00000 // 2 GiB - 2 MiB +#define MM_KSTACK_BASE 0x7FE00000 +#define MM_KSTACK_END 0x80000000 + +// Page Blocks are 12-bits wide (12 address bits used) +// Hence, the table is 16KiB large (and must be so aligned) +// and each block addresses 1MiB of data + +// First level table is aligned to 16KiB (restriction of TTBR reg) +// - VMSAv6 uses two TTBR regs, determined by bit 31 + +//#define KERNEL_BASE 0x80000000 // 2GiB + +#define MM_KHEAP_BASE 0x80800000 // 8MiB of kernel code +#define MM_KHEAP_MAX 0xC0000000 // ~1GiB of kernel heap + +#define MM_MODULE_MIN 0xC0000000 // - 0xD0000000 +#define MM_MODULE_MAX 0xCF000000 + +#define MM_GLOBALSTACKS 0xCF000000 // Global stacks +#define MM_GLOBALSTACKS_END 0xD0000000 + +// PMM Data, giving it 256MiB is overkill, but it's unused atm +#define MM_MAXPHYSPAGE (1024*1024) +// 2^(32-12) max pages +// 8.125 bytes per page (for bitmap allocation) +// = 8.125 MiB +#define MM_PMM_BASE 0xE0000000 +#define MM_PMM_END 0xF0000000 + +#define MM_HWMAP_BASE 0xF0000000 // Ent 0xF00 +#define MM_HWMAP_END 0xFE000000 +#define MM_TMPMAP_BASE 0xFE000000 +#define MM_TMPMAP_END 0xFF000000 + +#define MM_KERNEL_VFS 0xFF000000 // +#define MM_TABLE1KERN 0xFF800000 // - 0x???????? 4MiB +//#define MM_TABLE0KERN 0xFFC00000 // - 0xFFE04000 16KiB + +#endif diff --git a/KernelLand/Kernel/arch/armv6/include/options.h b/KernelLand/Kernel/arch/armv6/include/options.h new file mode 100644 index 00000000..4947158d --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/include/options.h @@ -0,0 +1,22 @@ +/* + * Acess2 ARMv6 Port + * - By John Hodge (thePowersGang) + * + * options.h + * - C/ASM Shared constants + */ +#ifndef _ARMV7_OPTIONS_H_ +#define _ARMV7_OPTIONS_H_ + +#define KERNEL_BASE 0x80000000 + +#if PLATFORM_is_raspberrypi +# define UART0_PADDR 0x7E215040 // Realview +#else +# error Unknown platform +#endif + +#define MM_KSTACK_SIZE 0x2000 // 2 Pages + +#endif + diff --git a/KernelLand/Kernel/arch/armv6/include/proc.h b/KernelLand/Kernel/arch/armv6/include/proc.h new file mode 100644 index 00000000..d6ef3d55 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/include/proc.h @@ -0,0 +1,48 @@ +/* + * Acess2 + * ARM7 Architecture + * + * proc.h - Arch-Dependent Process Management + */ +#ifndef _PROC_H_ +#define _PROC_H_ + +#define MAX_CPUS 4 +#define USER_MAX 0x80000000 + +// === STRUCTURES === +typedef struct { + Uint32 IP, SP; + Uint32 UserIP, UserSP; +} tTaskState; + +typedef struct { + Uint32 Base; +} tMemoryState; + +typedef struct { + union { + Uint32 Num; + Uint32 Error; + }; + union { + Uint32 Arg1; + Uint32 Return; + }; + union { + Uint32 Arg2; + Uint32 RetHi; + }; + Uint32 Arg3; + Uint32 Arg4; + Uint32 Arg5; + Uint32 Arg6; // R6 +} tSyscallRegs; + +// === MACROS === +#define HALT() do{}while(0) + +// === PROTOTYPES === + +#endif + diff --git a/KernelLand/Kernel/arch/armv6/lib.S b/KernelLand/Kernel/arch/armv6/lib.S new file mode 100644 index 00000000..e2f06130 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/lib.S @@ -0,0 +1,84 @@ +/* + * Acess2 ARM + * - By John Hodge (thePowersGang) + * + * arch/arm7/lib.S + * - Assembly editions of library functions + */ +#include "include/assembly.h" + +.globl __memcpy_byte +__memcpy_byte: +1: + tst r2, r2 @ Check counter + moveq pc, lr @ Return if zero + ldrb r3, [r1],#1 @ Read + strb r3, [r0],#1 @ Write + sub r2, #1 + b 1b + +@ +@ Pre-aligned memcpy (32-bit blocks) +@ +.globl __memcpy_align4 +__memcpy_align4: + push {r4} + mvn r3, #3 @ Mask for checking length + + @ 4 byte chunk copies +1: tst r2, r3 + ldrne r4, [r1],#4 + strne r4, [r0],#4 + subne r2, #4 + bne 1b + + @ single byte copies to finish off +2: tst r2, #3 + beq 3f + ldrb r4, [r1],#1 + strb r4, [r0],#1 + sub r2, #1 + b 2b + +3: pop {r4} + mov pc, lr + +@ +@ Division +@ +.globl __divmod32_asm +__divmod32_asm: + push {r4} + mov r4, #0 @ Return value + mov r3, #1 @ add value + + @ Scan up for first larger multiple of 2 +1: cmp r0, r1 @ N < D + bmi 2f @ ^^ + lsl r1, r1, #1 @ D <<= 1 + lsls r3, r3, #1 @ add <<= 1 + beq .err @ result is zero + b 1b + + @ Go back down +2: lsrs r3, r3, #1 @ add >>= 1 + beq 3f @ Done (value is zero) + lsr r1, r1, #1 @ D >>= 1 + cmp r0, r1 @ N < D + bmi 2b + sub r0, r1 @ N -= D + add r4, r3 @ ret += add + b 2b +3: + tst r2, r2 @ Remainder (if wanted) + strne r0,[r2] + mov r0, r4 @ Return value + pop {r4} + mov pc, lr +.err: + mov r0, #0 + tst r2, r2 + strne r0, [r2] + pop {r4} + mov pc, lr + diff --git a/KernelLand/Kernel/arch/armv6/lib.c b/KernelLand/Kernel/arch/armv6/lib.c new file mode 100644 index 00000000..7894e3ad --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/lib.c @@ -0,0 +1,224 @@ +/* + * Acess2 ARM7 Port + * + * lib.c - Library Functions + */ +#include +#include "../helpers.h" + +// === IMPORTS === +extern void __memcpy_align4(void *_dest, const void *_src, size_t _length); +extern void __memcpy_byte(void *_dest, const void *_src, size_t _length); +extern Uint32 __divmod32_asm(Uint32 Num, Uint32 Den, Uint32 *Rem); + +// === PROTOTYPES === +Uint64 __divmod64(Uint64 Num, Uint64 Den, Uint64 *Rem); +Uint32 __divmod32(Uint32 Num, Uint32 Den, Uint32 *Rem); +#if 0 +Uint64 __udivdi3(Uint64 Num, Uint64 Den); +Uint64 __umoddi3(Uint64 Num, Uint64 Den); +Uint32 __udivsi3(Uint32 Num, Uint32 Den); +Uint32 __umodsi3(Uint32 Num, Uint32 Den); +Sint32 __divsi3(Sint32 Num, Sint32 Den); +Sint32 __modsi3(Sint32 Num, Sint32 Den); +#endif + +// === CODE === +void *memcpy(void *_dest, const void *_src, size_t _length) +{ + Uint8 *dst8 = _dest; + const Uint8 *src8 = _src; + + if( ((tVAddr)_dest & 3) == 0 && ((tVAddr)_src & 3) == 0 ) + { + __memcpy_align4(_dest, _src, _length); + return _dest; + } + + // Handle small copies / Non-aligned + if( _length < 4 || ((tVAddr)_dest & 3) != ((tVAddr)_src & 3) ) + { + __memcpy_byte(_dest, _src, _length); + return _dest; + } + + // Force alignment + while( (tVAddr)dst8 & 3 ) *dst8 ++ = *src8++, _length --; + + __memcpy_align4(dst8, src8, _length); + + return _dest; +} + +int memcmp(const void *_m1, const void *_m2, size_t _length) +{ + const Uint32 *m1, *m2; + const Uint8 *m1_8 = _m1, *m2_8 = _m2; + + // Handle small copies / Non-aligned + if( _length < 4 || ((tVAddr)_m1 & 3) != ((tVAddr)_m1 & 3) ) + { + for( ; _length--; m1_8++,m2_8++ ) { + if(*m1_8 != *m2_8) return *m1_8 - *m2_8; + } + return 0; + } + + // Force alignment + for( ; (tVAddr)m1_8 & 3; m1_8 ++, m2_8 ++) { + if(*m1_8 != *m2_8) return *m1_8 - *m2_8; + } + m1 = (void *)m1_8; m2 = (void *)m2_8; + + // DWORD copies + for( ; _length > 3; _length -= 4, m1++, m2++) + if(*m1 != *m2) return *m1 - *m2; + + // Trailing bytes + m1_8 = (void*)m1; m2_8 = (void*)m2; + for( ; _length; _length --, m1_8++, m2_8++ ) + if(*m1_8 != *m2_8) return *m1_8 - *m2_8; + + return 0; +} + +void *memset(void *_dest, int _value, size_t _length) +{ + Uint32 *dst, val32; + Uint8 *dst8 = _dest; + + _value = (Uint8)_value; + + // Handle small copies + if( _length < 4 ) + { + for( ; _length--; dst8++ ) + *dst8 = _value; + return _dest; + } + + val32 = _value; + val32 |= val32 << 8; + val32 |= val32 << 16; + + // Force alignment + while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value; + dst = (void *)dst8; + + // DWORD copies + for( ; _length > 3; _length -= 4) + *dst++ = val32; + + // Trailing bytes + dst8 = (void*)dst; + for( ; _length; _length -- ) + *dst8 ++ = _value; + + return _dest; +} + +DEF_DIVMOD(64) +DEF_DIVMOD(32) + +Uint64 DivMod64U(Uint64 Num, Uint64 Den, Uint64 *Rem) +{ + Uint64 ret; + if(Den == 0) return 0; // TODO: #div0 + if(Num < Den) { + if(Rem) *Rem = Num; + return 0; + } + if(Num == 0) { + if(Rem) *Rem = 0; + return 0; + } + if(Den == 1) { + if(Rem) *Rem = 0; + return Num; + } + if(Den == 2) { + if(Rem) *Rem = Num & 1; + return Num >> 1; + } + if(Den == 16) { + if(Rem) *Rem = Num & 0xF; + return Num >> 4; + } + if(Den == 32) { + if(Rem) *Rem = Num & 0x1F; + return Num >> 5; + } + if(Den == 0x1000) { + if(Rem) *Rem = Num & 0xFFF; + return Num >> 12; + } + + if( !(Den >> 32) && !(Num >> 32) ) { + if(Rem) *Rem = 0; // Clear high bits + return __divmod32_asm(Num, Den, (Uint32*)Rem); + } + + ret = __divmod64(Num, Den, Rem); + return ret; +} + +#if 0 +// Unsigned Divide 64-bit Integer +Uint64 __udivdi3(Uint64 Num, Uint64 Den) +{ + return DivMod64U(Num, Den, NULL); +} + +// Unsigned Modulus 64-bit Integer +Uint64 __umoddi3(Uint64 Num, Uint64 Den) +{ + Uint64 ret = 0; + DivMod64U(Num, Den, &ret); + return ret; +} + +Uint32 __udivsi3(Uint32 Num, Uint32 Den) +{ + return __divmod32_asm(Num, Den, NULL); +} + +Uint32 __umodsi3(Uint32 Num, Uint32 Den) +{ + Uint32 rem; + __divmod32_asm(Num, Den, &rem); + return rem; +} +#endif + +static inline Sint32 DivMod32S(Sint32 Num, Sint32 Den, Sint32 *Rem) +{ + Sint32 ret = 1; + if( Num < 0 ) { + ret = -ret; + Num = -Num; + } + if( Den < 0 ) { + ret = -ret; + Den = -Den; + } + if(ret < 0) + ret = -__divmod32(Num, Den, (Uint32*)Rem); + else + ret = __divmod32(Num, Den, (Uint32*)Rem); + return ret; +} + +#if 0 +Sint32 __divsi3(Sint32 Num, Sint32 Den) +{ + return DivMod32S(Num, Den, NULL); +} + +Sint32 __modsi3(Sint32 Num, Sint32 Den) +{ + Sint32 rem; + DivMod32S(Num, Den, &rem); + return rem; +} +#endif + diff --git a/KernelLand/Kernel/arch/armv6/link.ld b/KernelLand/Kernel/arch/armv6/link.ld new file mode 100644 index 00000000..2ad5afed --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/link.ld @@ -0,0 +1,59 @@ +ENTRY (_start) + +_kernel_base = 0x80000000; +_usertext_vbase = 0xFFFFE000; + +SECTIONS +{ + . = 0; + .init : + { + *(.init) + } + . += _kernel_base; + .text : AT( ADDR(.text) - _kernel_base ) + { + *(.text*) + *(.rodata*) + } + __exidx_start = .; + .ARM.exidx : { *(.ARM.exidx*) } + __exidx_end = .; + .ARM.extab : { *(.ARM.extab*) } + + + /* HACKS: User accesible .text section */ + . = ALIGN(0x1000); + gUsertextPhysStart = . - _kernel_base; + . = _usertext_vbase; + .usertext : AT( gUsertextPhysStart ) + { + *(.usertext) + } + . += gUsertextPhysStart + _kernel_base - _usertext_vbase; + + /* 0x4000 (4 pages) alignment needed for root table */ + .data ALIGN(0x4000) : AT( ADDR(.data) - _kernel_base ) + { + *(.padata) + *(.data*) + + gKernelSymbols = .; + *(KEXPORT) + gKernelSymbolsEnd = .; + + gKernelModules = .; + *(KMODULES) + gKernelModulesEnd = .; + } + .bss : AT( ADDR(.bss) - _kernel_base ) + { + bss_start = .; + *(.bss*) + *(COMMON*) + . = ALIGN(0x1000); + *(.pabss) + bss_end = .; + } + gKernelEnd = .; +} diff --git a/KernelLand/Kernel/arch/armv6/main.c b/KernelLand/Kernel/arch/armv6/main.c new file mode 100644 index 00000000..248c17c5 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/main.c @@ -0,0 +1,96 @@ +/* + * Acess2 + * + * ARM7 Entrypoint + * arch/arm7/main.c + */ +#define DEBUG 0 + +#include +#include + +// === IMPORTS === +extern void Interrupts_Setup(void); +extern void Arch_LoadBootModules(void); +extern void Heap_Install(void); +extern void Threads_Init(void); +extern void System_Init(const char *Commandline); + +// === PROTOTYPES === + int kmain(void); +Uint32 ARMv7_int_HandleSyscalls(Uint32 Num, Uint32 *Args); + +// === CODE === +int kmain(void) +{ + LogF("Acess2 ARMv7 v"EXPAND_STR(KERNEL_VERSION)"\n"); + LogF(" Git Hash %s\n", gsGitHash); + LogF(" Build %i\n", BUILD_NUM); + + MM_SetupPhys(); + + LogF("Heap Setup...\n"); + Heap_Install(); + + LogF("Threads Init...\n"); + Threads_Init(); + + LogF("VFS Init...\n"); + VFS_Init(); + + // Boot modules? + Module_EnsureLoaded("armv7_GIC"); + + // + LogF("Moving to arch-independent init\n"); + #if PLATFORM_is_tegra2 + System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=Tegra2Vid"); + #else + System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=PL110"); + #endif +// System_Init("Acess2.armv7.bin /Acess=initrd:"); + //TODO: + LogF("End of kmain(), for(;;) Threads_Sleep();\n"); + for(;;) + Threads_Sleep(); +} + +void Arch_LoadBootModules(void) +{ +} + +Uint32 ARMv7_int_HandleSyscalls(Uint32 Num, Uint32 *Args) +{ + Uint32 ret = -1, err = 0; + Uint32 addr; + ENTER("iNum xArgs[0] xArgs[1] xArgs[2] xArgs[3]", + Num, Args[0], Args[1], Args[2], Args[3] + ); + switch(Num) + { + case 1: +// Log_Debug("ARMv7", "__clear_cache(%p, %p)", Args[0], Args[1]); + // Align + Args[0] &= ~0xFFF; + Args[1] += 0xFFF; Args[1] &= ~0xFFF; + // Invalidate! + for( addr = Args[0]; addr < Args[1]; addr += 0x1000 ) + { + LOG("addr = %p", addr); + __asm__ __volatile__ ( + "mcrlt p15, 0, %0, c7, c5, 1;\n\t" + "mcrlt p15, 0, %0, c7, c6, 1;\n\t" + : + : "r" (addr) + ); + } + ret = 0; + break; + } + Args[0] = ret; // RetLow + Args[1] = 0; // RetHi + Args[2] = err; // Errno + LEAVE('x', ret); + return ret; +} + diff --git a/KernelLand/Kernel/arch/armv6/mm_phys.c b/KernelLand/Kernel/arch/armv6/mm_phys.c new file mode 100644 index 00000000..5e4a2428 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/mm_phys.c @@ -0,0 +1,60 @@ +/* + * Acess2 + * + * ARM7 Physical Memory Manager + * arch/arm7/mm_phys.c + */ +#define DEBUG 0 + +#include +#include + +#define MM_NUM_RANGES 1 // Single range +#define MM_RANGE_MAX 0 +#define TRACE_ALLOCS 0 + +#define NUM_STATIC_ALLOC 4 + +char gStaticAllocPages[NUM_STATIC_ALLOC][PAGE_SIZE] __attribute__ ((section(".padata"))); +tPAddr gaiStaticAllocPages[NUM_STATIC_ALLOC] = { + (tPAddr)(&gStaticAllocPages[0]) - KERNEL_BASE, + (tPAddr)(&gStaticAllocPages[1]) - KERNEL_BASE, + (tPAddr)(&gStaticAllocPages[2]) - KERNEL_BASE, + (tPAddr)(&gStaticAllocPages[3]) - KERNEL_BASE +}; +extern char gKernelEnd[]; + + +#include + +//#define REALVIEW_LOWRAM_SIZE 0x10000000 +#define REALVIEW_LOWRAM_SIZE (32*1024*1024) + +void MM_SetupPhys(void) +{ + LogF("MM_SetupPhys: ()\n"); + MM_Tpl_InitPhys( REALVIEW_LOWRAM_SIZE/0x1000, NULL ); +} + +int MM_int_GetMapEntry( void *Data, int Index, tPAddr *Start, tPAddr *Length ) +{ + switch(Index) + { + case 0: + *Start = ((tVAddr)&gKernelEnd - KERNEL_BASE + 0xFFF) & ~0xFFF; + *Length = REALVIEW_LOWRAM_SIZE - *Start; + return 1; + default: + return 0; + } +} + +/** + * \brief Takes a physical address and returns the ID of its range + * \param Addr Physical address of page + * \return Range ID from eMMPhys_Ranges + */ +int MM_int_GetRangeID( tPAddr Addr ) +{ + return MM_RANGE_MAX; // ARM doesn't need ranges +} diff --git a/KernelLand/Kernel/arch/armv6/mm_virt.c b/KernelLand/Kernel/arch/armv6/mm_virt.c new file mode 100644 index 00000000..2dc1147e --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/mm_virt.c @@ -0,0 +1,1080 @@ +/* + * Acess2 + * + * ARM7 Virtual Memory Manager + * - arch/arm7/mm_virt.c + */ +#define DEBUG 0 +#include +#include +#include + +#define TRACE_MAPS 0 + +#define AP_KRW_ONLY 1 // Kernel page +#define AP_KRO_ONLY 5 // Kernel RO page +#define AP_RW_BOTH 3 // Standard RW +#define AP_RO_BOTH 7 // COW Page +#define AP_RO_USER 2 // User RO Page +#define PADDR_MASK_LVL1 0xFFFFFC00 + +// === IMPORTS === +extern Uint32 kernel_table0[]; + +// === TYPES === +typedef struct +{ + tPAddr PhysAddr; + Uint8 Size; + Uint8 Domain; + BOOL bExecutable; + BOOL bGlobal; + BOOL bShared; + int AP; +} tMM_PageInfo; + +//#define FRACTAL(table1, addr) ((table1)[ (0xFF8/4*1024) + ((addr)>>20)]) +#define FRACTAL(table1, addr) ((table1)[ (0xFF8/4*1024) + ((addr)>>22)]) +#define USRFRACTAL(addr) (*((Uint32*)(0x7FDFF000) + ((addr)>>22))) +#define TLBIALL() __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)) +#define TLBIMVA(addr) __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 1" : : "r" (((addr)&~0xFFF)|1):"memory") +#define DCCMVAC(addr) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 1" : : "r" ((addr)&~0xFFF)) + +// === PROTOTYPES === +void MM_int_GetTables(tVAddr VAddr, Uint32 **Table0, Uint32 **Table1); + int MM_int_AllocateCoarse(tVAddr VAddr, int Domain); + int MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi); + int MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi); +tVAddr MM_NewUserStack(void); +tPAddr MM_AllocateZero(tVAddr VAddr); +tPAddr MM_AllocateRootTable(void); +void MM_int_CloneTable(Uint32 *DestEnt, int Table); +tPAddr MM_Clone(void); +tVAddr MM_NewKStack(int bGlobal); +void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info); +//void MM_DumpTables(tVAddr Start, tVAddr End); +void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch); + +// === GLOBALS === +tPAddr giMM_ZeroPage; + +// === CODE === +int MM_InitialiseVirtual(void) +{ + return 0; +} + +void MM_int_GetTables(tVAddr VAddr, Uint32 **Table0, Uint32 **Table1) +{ + if(VAddr & 0x80000000) { + *Table0 = (void*)&kernel_table0; // Level 0 + *Table1 = (void*)MM_TABLE1KERN; // Level 1 + } + else { + *Table0 = (void*)MM_TABLE0USER; + *Table1 = (void*)MM_TABLE1USER; + } +} + +int MM_int_AllocateCoarse(tVAddr VAddr, int Domain) +{ + Uint32 *table0, *table1; + Uint32 *desc; + tPAddr paddr; + + ENTER("xVAddr iDomain", VAddr, Domain); + + MM_int_GetTables(VAddr, &table0, &table1); + + VAddr &= ~(0x400000-1); // 4MiB per "block", 1 Page + + desc = &table0[ VAddr>>20]; + LOG("desc = %p", desc); + + // table0: 4 bytes = 1 MiB + + LOG("desc[0] = %x", desc[0]); + LOG("desc[1] = %x", desc[1]); + LOG("desc[2] = %x", desc[2]); + LOG("desc[3] = %x", desc[3]); + + if( (desc[0] & 3) != 0 || (desc[1] & 3) != 0 + || (desc[2] & 3) != 0 || (desc[3] & 3) != 0 ) + { + // Error? + LEAVE('i', 1); + return 1; + } + + paddr = MM_AllocPhys(); + if( !paddr ) + { + // Error + LEAVE('i', 2); + return 2; + } + + *desc = paddr | (Domain << 5) | 1; + desc[1] = desc[0] + 0x400; + desc[2] = desc[0] + 0x800; + desc[3] = desc[0] + 0xC00; + + if( VAddr < 0x80000000 ) { + USRFRACTAL(VAddr) = paddr | 0x13; + } + else { + FRACTAL(table1, VAddr) = paddr | 0x13; + } + + // TLBIALL + TLBIALL(); + + memset( (void*)&table1[ (VAddr >> 12) & ~(1024-1) ], 0, 0x1000 ); + + LEAVE('i', 0); + return 0; +} + +int MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi) +{ + Uint32 *table0, *table1; + Uint32 *desc; + + ENTER("pVAddr ppi", VAddr, pi); + + MM_int_GetTables(VAddr, &table0, &table1); + + desc = &table0[ VAddr >> 20 ]; + LOG("desc = %p", desc); + + switch(pi->Size) + { + case 12: // Small Page + case 16: // Large Page + LOG("Page"); + if( (*desc & 3) == 0 ) { + MM_int_AllocateCoarse( VAddr, pi->Domain ); + } + desc = &table1[ VAddr >> 12 ]; + LOG("desc (2) = %p", desc); + if( pi->Size == 12 ) + { + // Small page + // - Error if overwriting a large page + if( (*desc & 3) == 1 ) LEAVE_RET('i', 1); + if( pi->PhysAddr == 0 ) { + *desc = 0; + TLBIMVA( VAddr ); + DCCMVAC( (tVAddr) desc ); +// #warning "HACK: TLBIALL" +// TLBIALL(); + LEAVE('i', 0); + return 0; + } + + *desc = (pi->PhysAddr & 0xFFFFF000) | 2; + if(!pi->bExecutable) *desc |= 1; // XN + if(!pi->bGlobal) *desc |= 1 << 11; // nG + if( pi->bShared) *desc |= 1 << 10; // S + *desc |= (pi->AP & 3) << 4; // AP + *desc |= ((pi->AP >> 2) & 1) << 9; // APX + TLBIMVA( VAddr ); +// #warning "HACK: TLBIALL" +// TLBIALL(); + DCCMVAC( (tVAddr) desc ); + LEAVE('i', 0); + return 0; + } + else + { + // Large page + Log_Warning("MMVirt", "TODO: Implement large pages in MM_int_SetPageInfo"); + } + break; + case 20: // Section or unmapped + Log_Warning("MMVirt", "TODO: Implement sections in MM_int_SetPageInfo"); + break; + case 24: // Supersection + // Error if not aligned + if( VAddr & 0xFFFFFF ) { + LEAVE('i', 1); + return 1; + } + if( (*desc & 3) == 0 || ((*desc & 3) == 2 && (*desc & (1 << 18))) ) + { + if( pi->PhysAddr == 0 ) { + *desc = 0; + } + else { + // Apply + *desc = pi->PhysAddr & 0xFF000000; +// *desc |= ((pi->PhysAddr >> 32) & 0xF) << 20; +// *desc |= ((pi->PhysAddr >> 36) & 0x7) << 5; + *desc |= 2 | (1 << 18); + } + // TODO: Apply to all entries + Log_Warning("MMVirt", "TODO: Apply changes to all entries of supersections"); + LEAVE('i', 0); + return 0; + } + // TODO: What here? + Log_Warning("MMVirt", "TODO: 24-bit not on supersection?"); + LEAVE('i', 1); + return 1; + } + + LEAVE('i', 1); + return 1; +} + +int MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi) +{ + Uint32 *table0, *table1; + Uint32 desc; + +// LogF("MM_int_GetPageInfo: VAddr=%p, pi=%p\n", VAddr, pi); + + MM_int_GetTables(VAddr, &table0, &table1); + + desc = table0[ VAddr >> 20 ]; + +// if( VAddr > 0x90000000) +// LOG("table0 desc(%p) = %x", &table0[ VAddr >> 20 ], desc); + + pi->bExecutable = 1; + pi->bGlobal = 0; + pi->bShared = 0; + pi->AP = 0; + + switch( (desc & 3) ) + { + // 0: Unmapped + case 0: + pi->PhysAddr = 0; + pi->Size = 20; + pi->Domain = 0; + return 1; + + // 1: Coarse page table + case 1: + // Domain from top level table + pi->Domain = (desc >> 5) & 7; + // Get next level + desc = table1[ VAddr >> 12 ]; +// LOG("table1 desc(%p) = %x", &table1[ VAddr >> 12 ], desc); + switch( desc & 3 ) + { + // 0: Unmapped + case 0: + pi->Size = 12; + return 1; + // 1: Large Page (64KiB) + case 1: + pi->Size = 16; + pi->PhysAddr = desc & 0xFFFF0000; + pi->AP = ((desc >> 4) & 3) | (((desc >> 9) & 1) << 2); + pi->bExecutable = !(desc & 0x8000); + pi->bShared = (desc >> 10) & 1; + return 0; + // 2/3: Small page + case 2: + case 3: + pi->Size = 12; + pi->PhysAddr = desc & 0xFFFFF000; + pi->bExecutable = !(desc & 1); + pi->bGlobal = !(desc >> 11); + pi->bShared = (desc >> 10) & 1; + pi->AP = ((desc >> 4) & 3) | (((desc >> 9) & 1) << 2); + return 0; + } + return 1; + + // 2: Section (or Supersection) + case 2: + if( desc & (1 << 18) ) { + // Supersection + pi->PhysAddr = desc & 0xFF000000; + pi->PhysAddr |= (Uint64)((desc >> 20) & 0xF) << 32; + pi->PhysAddr |= (Uint64)((desc >> 5) & 0x7) << 36; + pi->Size = 24; + pi->Domain = 0; // Supersections default to zero + pi->AP = ((desc >> 10) & 3) | (((desc >> 15) & 1) << 2); + return 0; + } + + // Section + pi->PhysAddr = desc & 0xFFF80000; + pi->Size = 20; + pi->Domain = (desc >> 5) & 7; + pi->AP = ((desc >> 10) & 3) | (((desc >> 15) & 1) << 2); + return 0; + + // 3: Reserved (invalid) + case 3: + pi->PhysAddr = 0; + pi->Size = 20; + pi->Domain = 0; + return 2; + } + return 2; +} + +// --- Exports --- +tPAddr MM_GetPhysAddr(const void *Ptr) +{ + tVAddr VAddr = (tPAddr)Ptr; + tMM_PageInfo pi; + if( MM_int_GetPageInfo(VAddr, &pi) ) + return 0; + return pi.PhysAddr | (VAddr & ((1 << pi.Size)-1)); +} + +Uint MM_GetFlags(tVAddr VAddr) +{ + tMM_PageInfo pi; + int ret; + + if( MM_int_GetPageInfo(VAddr, &pi) ) + return 0; + + ret = 0; + + switch(pi.AP) + { + case 0: + break; + case AP_KRW_ONLY: + ret |= MM_PFLAG_KERNEL; + break; + case AP_KRO_ONLY: + ret |= MM_PFLAG_KERNEL|MM_PFLAG_RO; + break; + case AP_RW_BOTH: + break; + case AP_RO_BOTH: + ret |= MM_PFLAG_COW; + break; + case AP_RO_USER: + ret |= MM_PFLAG_RO; + break; + } + + if( pi.bExecutable ) ret |= MM_PFLAG_EXEC; + return ret; +} + +void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) +{ + tMM_PageInfo pi; + Uint curFlags; + + if( MM_int_GetPageInfo(VAddr, &pi) ) + return ; + + curFlags = MM_GetFlags(VAddr); + if( (curFlags & Mask) == Flags ) + return ; + curFlags &= ~Mask; + curFlags |= Flags; + + if( curFlags & MM_PFLAG_COW ) + pi.AP = AP_RO_BOTH; + else + { + switch(curFlags & (MM_PFLAG_KERNEL|MM_PFLAG_RO) ) + { + case 0: + pi.AP = AP_RW_BOTH; break; + case MM_PFLAG_KERNEL: + pi.AP = AP_KRW_ONLY; break; + case MM_PFLAG_RO: + pi.AP = AP_RO_USER; break; + case MM_PFLAG_KERNEL|MM_PFLAG_RO: + pi.AP = AP_KRO_ONLY; break; + } + } + + pi.bExecutable = !!(curFlags & MM_PFLAG_EXEC); + + MM_int_SetPageInfo(VAddr, &pi); +} + +int MM_IsValidBuffer(tVAddr Addr, size_t Size) +{ + tMM_PageInfo pi; + int bUser = 0; + + Size += Addr & (PAGE_SIZE-1); + Addr &= ~(PAGE_SIZE-1); + + if( MM_int_GetPageInfo(Addr, &pi) ) return 0; + Addr += PAGE_SIZE; + + if(pi.AP != AP_KRW_ONLY && pi.AP != AP_KRO_ONLY) + bUser = 1; + + while( Size >= PAGE_SIZE ) + { + if( MM_int_GetPageInfo(Addr, &pi) ) + return 0; + if(bUser && (pi.AP == AP_KRW_ONLY || pi.AP == AP_KRO_ONLY)) + return 0; + Addr += PAGE_SIZE; + Size -= PAGE_SIZE; + } + + return 1; +} + +int MM_Map(tVAddr VAddr, tPAddr PAddr) +{ + tMM_PageInfo pi = {0}; + #if TRACE_MAPS + Log("MM_Map %P=>%p", PAddr, VAddr); + #endif + + pi.PhysAddr = PAddr; + pi.Size = 12; + if(VAddr < USER_STACK_TOP) + pi.AP = AP_RW_BOTH; + else + pi.AP = AP_KRW_ONLY; // Kernel Read/Write + pi.bExecutable = 1; + if( MM_int_SetPageInfo(VAddr, &pi) ) { +// MM_DerefPhys(pi.PhysAddr); + return 0; + } + return pi.PhysAddr; +} + +tPAddr MM_Allocate(tVAddr VAddr) +{ + tMM_PageInfo pi = {0}; + + ENTER("pVAddr", VAddr); + + pi.PhysAddr = MM_AllocPhys(); + if( pi.PhysAddr == 0 ) LEAVE_RET('i', 0); + pi.Size = 12; + if(VAddr < USER_STACK_TOP) + pi.AP = AP_RW_BOTH; + else + pi.AP = AP_KRW_ONLY; + pi.bExecutable = 0; + if( MM_int_SetPageInfo(VAddr, &pi) ) { + MM_DerefPhys(pi.PhysAddr); + LEAVE('i', 0); + return 0; + } + LEAVE('x', pi.PhysAddr); + return pi.PhysAddr; +} + +tPAddr MM_AllocateZero(tVAddr VAddr) +{ + if( !giMM_ZeroPage ) { + giMM_ZeroPage = MM_Allocate(VAddr); + MM_RefPhys(giMM_ZeroPage); + memset((void*)VAddr, 0, PAGE_SIZE); + } + else { + MM_RefPhys(giMM_ZeroPage); + MM_Map(VAddr, giMM_ZeroPage); + } + MM_SetFlags(VAddr, MM_PFLAG_COW, MM_PFLAG_COW); + return giMM_ZeroPage; +} + +void MM_Deallocate(tVAddr VAddr) +{ + tMM_PageInfo pi; + + if( MM_int_GetPageInfo(VAddr, &pi) ) return ; + if( pi.PhysAddr == 0 ) return; + MM_DerefPhys(pi.PhysAddr); + + pi.PhysAddr = 0; + pi.AP = 0; + pi.bExecutable = 0; + MM_int_SetPageInfo(VAddr, &pi); +} + +tPAddr MM_AllocateRootTable(void) +{ + tPAddr ret; + + ret = MM_AllocPhysRange(2, -1); + if( ret & 0x1000 ) { + MM_DerefPhys(ret); + MM_DerefPhys(ret+0x1000); + ret = MM_AllocPhysRange(3, -1); + if( ret & 0x1000 ) { + MM_DerefPhys(ret); + ret += 0x1000; +// Log("MM_AllocateRootTable: Second try not aligned, %P", ret); + } + else { + MM_DerefPhys(ret + 0x2000); +// Log("MM_AllocateRootTable: Second try aligned, %P", ret); + } + } +// else +// Log("MM_AllocateRootTable: Got it in one, %P", ret); + return ret; +} + +void MM_int_CloneTable(Uint32 *DestEnt, int Table) +{ + tPAddr table; + Uint32 *tmp_map; + Uint32 *cur = (void*)MM_TABLE1USER; +// Uint32 *cur = &FRACTAL(MM_TABLE1USER,0); + int i; + + table = MM_AllocPhys(); + if(!table) return ; + + cur += 256*Table; + + tmp_map = MM_MapTemp(table); + + for( i = 0; i < 1024; i ++ ) + { +// Log_Debug("MMVirt", "cur[%i] (%p) = %x", Table*256+i, &cur[Table*256+i], cur[Table*256+i]); + switch(cur[i] & 3) + { + case 0: tmp_map[i] = 0; break; + case 1: + tmp_map[i] = 0; + Log_Error("MMVirt", "TODO: Support large pages in MM_int_CloneTable (%p)", (Table*256+i)*0x1000); + // Large page? + break; + case 2: + case 3: + // Small page + // - If full RW +// Debug("%p cur[%i] & 0x230 = 0x%x", Table*256*0x1000, i, cur[i] & 0x230); + if( (cur[i] & 0x230) == 0x010 ) + { + void *dst, *src; + tPAddr newpage; + newpage = MM_AllocPhys(); + src = (void*)( (Table*256+i)*0x1000 ); + dst = MM_MapTemp(newpage); +// Debug("Taking a copy of kernel page %p (%P)", src, cur[i] & ~0xFFF); + memcpy(dst, src, PAGE_SIZE); + MM_FreeTemp( dst ); + tmp_map[i] = newpage | (cur[i] & 0xFFF); + } + else + { + if( (cur[i] & 0x230) == 0x030 ) + cur[i] |= 0x200; // Set to full RO (Full RO=COW, User RO = RO) + tmp_map[i] = cur[i]; + MM_RefPhys( tmp_map[i] & ~0xFFF ); + } + break; + } + } + MM_FreeTemp( tmp_map ); + + DestEnt[0] = table + 0*0x400 + 1; + DestEnt[1] = table + 1*0x400 + 1; + DestEnt[2] = table + 2*0x400 + 1; + DestEnt[3] = table + 3*0x400 + 1; +} + +tPAddr MM_Clone(void) +{ + tPAddr ret; + Uint32 *new_lvl1_1, *new_lvl1_2, *cur; + Uint32 *tmp_map; + int i; + +// MM_DumpTables(0, KERNEL_BASE); + + ret = MM_AllocateRootTable(); + + cur = (void*)MM_TABLE0USER; + new_lvl1_1 = MM_MapTemp(ret); + new_lvl1_2 = MM_MapTemp(ret+0x1000); + tmp_map = new_lvl1_1; + for( i = 0; i < 0x800-4; i ++ ) + { + // HACK! Ignore the original identity mapping + if( i == 0 && Threads_GetTID() == 0 ) { + tmp_map[0] = 0; + continue; + } + if( i == 0x400 ) + tmp_map = &new_lvl1_2[-0x400]; + switch( cur[i] & 3 ) + { + case 0: tmp_map[i] = 0; break; + case 1: + MM_int_CloneTable(&tmp_map[i], i); + i += 3; // Tables are alocated in blocks of 4 + break; + case 2: + case 3: + Log_Error("MMVirt", "TODO: Support Sections/Supersections in MM_Clone (i=%i)", i); + tmp_map[i] = 0; + break; + } + } + + // Allocate Fractal table + { + int j, num; + tPAddr tmp = MM_AllocPhys(); + Uint32 *table = MM_MapTemp(tmp); + Uint32 sp; + register Uint32 __SP asm("sp"); + + // Map table to last 4MiB of user space + new_lvl1_2[0x3FC] = tmp + 0*0x400 + 1; + new_lvl1_2[0x3FD] = tmp + 1*0x400 + 1; + new_lvl1_2[0x3FE] = tmp + 2*0x400 + 1; + new_lvl1_2[0x3FF] = tmp + 3*0x400 + 1; + + tmp_map = new_lvl1_1; + for( j = 0; j < 512; j ++ ) + { + if( j == 256 ) + tmp_map = &new_lvl1_2[-0x400]; + if( (tmp_map[j*4] & 3) == 1 ) + { + table[j] = tmp_map[j*4] & PADDR_MASK_LVL1;// 0xFFFFFC00; + table[j] |= 0x813; // nG, Kernel Only, Small page, XN + } + else + table[j] = 0; + } + // Fractal + table[j++] = (ret + 0x0000) | 0x813; + table[j++] = (ret + 0x1000) | 0x813; + // Nuke the rest + for( ; j < 1024; j ++ ) + table[j] = 0; + + // Get kernel stack bottom + sp = __SP & ~(MM_KSTACK_SIZE-1); + j = (sp / 0x1000) % 1024; + num = MM_KSTACK_SIZE/0x1000; + +// Log("num = %i, sp = %p, j = %i", num, sp, j); + + // Copy stack pages + for(; num--; j ++, sp += 0x1000) + { + tVAddr page; + void *tmp_page; + + page = MM_AllocPhys(); +// Log("page = %P", page); + table[j] = page | 0x813; + + tmp_page = MM_MapTemp(page); + memcpy(tmp_page, (void*)sp, 0x1000); + MM_FreeTemp( tmp_page ); + } + + MM_FreeTemp( table ); + } + + MM_FreeTemp( new_lvl1_1 ); + MM_FreeTemp( new_lvl1_2 ); + +// Log("MM_Clone: ret = %P", ret); + + return ret; +} + +void MM_ClearUser(void) +{ + int i, j; + const int user_table_count = USER_STACK_TOP / (256*0x1000); + Uint32 *cur = (void*)MM_TABLE0USER; + Uint32 *tab; + +// MM_DumpTables(0, 0x80000000); + +// Log("user_table_count = %i (as opposed to %i)", user_table_count, 0x800-4); + + for( i = 0; i < user_table_count; i ++ ) + { + switch( cur[i] & 3 ) + { + case 0: break; // Already unmapped + case 1: // Sub pages + tab = (void*)(MM_TABLE1USER + i*256*sizeof(Uint32)); + for( j = 0; j < 1024; j ++ ) + { + switch( tab[j] & 3 ) + { + case 0: break; // Unmapped + case 1: + Log_Error("MMVirt", "TODO: Support large pages in MM_ClearUser"); + break; + case 2: + case 3: + MM_DerefPhys( tab[j] & ~(PAGE_SIZE-1) ); + break; + } + } + MM_DerefPhys( cur[i] & ~(PAGE_SIZE-1) ); + cur[i+0] = 0; + cur[i+1] = 0; + cur[i+2] = 0; + i += 3; + break; + case 2: + case 3: + Log_Error("MMVirt", "TODO: Implement sections/supersections in MM_ClearUser"); + break; + } + cur[i] = 0; + } + + // Final block of 4 tables are KStack + i = 0x800 - 4; + + // Clear out unused stacks + { + register Uint32 __SP asm("sp"); + int cur_stack_base = ((__SP & ~(MM_KSTACK_SIZE-1)) / PAGE_SIZE) % 1024; + + tab = (void*)(MM_TABLE1USER + i*256*sizeof(Uint32)); + + // First 512 is the Table1 mapping + 2 for Table0 mapping + for( j = 512+2; j < 1024; j ++ ) + { + // Skip current stack + if( j == cur_stack_base ) { + j += (MM_KSTACK_SIZE / PAGE_SIZE) - 1; + continue ; + } + if( !(tab[j] & 3) ) continue; + ASSERT( (tab[j] & 3) == 2 ); + MM_DerefPhys( tab[j] & ~(PAGE_SIZE) ); + tab[j] = 0; + } + } + + +// MM_DumpTables(0, 0x80000000); +} + +void *MM_MapTemp(tPAddr PAddr) +{ + tVAddr ret; + tMM_PageInfo pi; + + for( ret = MM_TMPMAP_BASE; ret < MM_TMPMAP_END - PAGE_SIZE; ret += PAGE_SIZE ) + { + if( MM_int_GetPageInfo(ret, &pi) == 0 ) + continue; + +// Log("MapTemp %P at %p by %p", PAddr, ret, __builtin_return_address(0)); + MM_RefPhys(PAddr); // Counter the MM_Deallocate in FreeTemp + MM_Map(ret, PAddr); + + return (void*)ret; + } + Log_Warning("MMVirt", "MM_MapTemp: All slots taken"); + return 0; +} + +void MM_FreeTemp(void *Ptr) +{ + tVAddr VAddr = (tVAddr)Ptr; + if( VAddr < MM_TMPMAP_BASE || VAddr >= MM_TMPMAP_END ) { + Log_Warning("MMVirt", "MM_FreeTemp: Passed an addr not from MM_MapTemp (%p)", VAddr); + return ; + } + + MM_Deallocate(VAddr); +} + +tVAddr MM_MapHWPages(tPAddr PAddr, Uint NPages) +{ + tVAddr ret; + int i; + tMM_PageInfo pi; + + ENTER("xPAddr iNPages", PAddr, NPages); + + // Scan for a location + for( ret = MM_HWMAP_BASE; ret < MM_HWMAP_END - NPages * PAGE_SIZE; ret += PAGE_SIZE ) + { +// LOG("checking %p", ret); + // Check if there is `NPages` free pages + for( i = 0; i < NPages; i ++ ) + { + if( MM_int_GetPageInfo(ret + i*PAGE_SIZE, &pi) == 0 ) + break; + } + // Nope, jump to after the used page found and try again +// LOG("i = %i, ==? %i", i, NPages); + if( i != NPages ) { + ret += i * PAGE_SIZE; + continue ; + } + + // Map the pages + for( i = 0; i < NPages; i ++ ) + MM_Map(ret+i*PAGE_SIZE, PAddr+i*PAGE_SIZE); + // and return + LEAVE('p', ret); + return ret; + } + Log_Warning("MMVirt", "MM_MapHWPages: No space for a %i page block", NPages); + LEAVE('p', 0); + return 0; +} + +tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PAddr) +{ + tPAddr phys; + tVAddr ret; + + phys = MM_AllocPhysRange(Pages, MaxBits); + if(!phys) { + Log_Warning("MMVirt", "No space left for a %i page block (MM_AllocDMA)", Pages); + return 0; + } + + ret = MM_MapHWPages(phys, Pages); + *PAddr = phys; + + return ret; +} + +void MM_UnmapHWPages(tVAddr Vaddr, Uint Number) +{ + Log_Error("MMVirt", "TODO: Implement MM_UnmapHWPages"); +} + +tVAddr MM_NewKStack(int bShared) +{ + tVAddr min_addr, max_addr; + tVAddr addr, ofs; + + if( bShared ) { + min_addr = MM_GLOBALSTACKS; + max_addr = MM_GLOBALSTACKS_END; + } + else { + min_addr = MM_KSTACK_BASE; + max_addr = MM_KSTACK_END; + } + + // Locate a free slot + for( addr = min_addr; addr < max_addr; addr += MM_KSTACK_SIZE ) + { + tMM_PageInfo pi; + if( MM_int_GetPageInfo(addr+MM_KSTACK_SIZE-PAGE_SIZE, &pi) ) break; + } + + // Check for an error + if(addr >= max_addr) { + return 0; + } + + // 1 guard page + for( ofs = PAGE_SIZE; ofs < MM_KSTACK_SIZE; ofs += PAGE_SIZE ) + { + if( MM_Allocate(addr + ofs) == 0 ) + { + while(ofs) + { + ofs -= PAGE_SIZE; + MM_Deallocate(addr + ofs); + } + Log_Warning("MMVirt", "MM_NewKStack: Unable to allocate"); + return 0; + } + } + return addr + ofs; +} + +tVAddr MM_NewUserStack(void) +{ + tVAddr addr, ofs; + + addr = USER_STACK_TOP - USER_STACK_SIZE; + if( MM_GetPhysAddr( (void*)(addr + PAGE_SIZE) ) ) { + Log_Error("MMVirt", "Unable to create initial user stack, addr %p taken", + addr + PAGE_SIZE + ); + return 0; + } + + // 1 guard page + for( ofs = PAGE_SIZE; ofs < USER_STACK_SIZE; ofs += PAGE_SIZE ) + { + tPAddr rv; + if(ofs >= USER_STACK_SIZE - USER_STACK_COMM) + rv = MM_Allocate(addr + ofs); + else + rv = MM_AllocateZero(addr + ofs); + if(rv == 0) + { + while(ofs) + { + ofs -= PAGE_SIZE; + MM_Deallocate(addr + ofs); + } + Log_Warning("MMVirt", "MM_NewUserStack: Unable to allocate"); + return 0; + } + MM_SetFlags(addr+ofs, 0, MM_PFLAG_KERNEL); + } +// Log("Return %p", addr + ofs); +// MM_DumpTables(0, 0x80000000); + return addr + ofs; +} + +void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info) +{ + if( giMM_ZeroPage && Info->PhysAddr == giMM_ZeroPage ) + { + Debug("%p => %8s - 0x%7x %i %x %s", + Start, "ZERO", Len, + Info->Domain, Info->AP, + Info->bGlobal ? "G" : "nG" + ); + } + else + { + Debug("%p => %8x - 0x%7x %i %x %s", + Start, Info->PhysAddr-Len, Len, + Info->Domain, Info->AP, + Info->bGlobal ? "G" : "nG" + ); + } +} + +void MM_DumpTables(tVAddr Start, tVAddr End) +{ + tVAddr range_start = 0, addr; + tMM_PageInfo pi, pi_old; + int i = 0, inRange=0; + + memset(&pi_old, 0, sizeof(pi_old)); + + Debug("Page Table Dump (%p to %p):", Start, End); + range_start = Start; + for( addr = Start; i == 0 || (addr && addr < End); i = 1 ) + { + int rv; +// Log("addr = %p", addr); + rv = MM_int_GetPageInfo(addr, &pi); + if( rv + || pi.Size != pi_old.Size + || pi.Domain != pi_old.Domain + || pi.AP != pi_old.AP + || pi.bGlobal != pi_old.bGlobal + || pi_old.PhysAddr != pi.PhysAddr ) + { + if(inRange) { + MM_int_DumpTableEnt(range_start, addr - range_start, &pi_old); + } + addr &= ~((1 << pi.Size)-1); + range_start = addr; + } + + pi_old = pi; + // Handle the zero page + if( !giMM_ZeroPage || pi_old.Size != 12 || pi_old.PhysAddr != giMM_ZeroPage ) + pi_old.PhysAddr += 1 << pi_old.Size; + addr += 1 << pi_old.Size; + inRange = (rv == 0); + } + if(inRange) + MM_int_DumpTableEnt(range_start, addr - range_start, &pi); + Debug("Done"); +} + +// NOTE: Runs in abort context, not much difference, just a smaller stack +void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch) +{ + int rv; + tMM_PageInfo pi; + + rv = MM_int_GetPageInfo(Addr, &pi); + + // Check for COW + if( rv == 0 && pi.AP == AP_RO_BOTH ) + { + pi.AP = AP_RW_BOTH; + if( giMM_ZeroPage && pi.PhysAddr == giMM_ZeroPage ) + { + tPAddr newpage; + newpage = MM_AllocPhys(); + if( !newpage ) { + Log_Error("MMVirt", "Unable to allocate new page for COW of ZERO"); + for(;;); + } + + #if TRACE_COW + Log_Notice("MMVirt", "COW %p caused by %p, ZERO duped to %P (RefCnt(%i)--)", Addr, PC, + newpage, MM_GetRefCount(pi.PhysAddr)); + #endif + + MM_DerefPhys(pi.PhysAddr); + pi.PhysAddr = newpage; + pi.AP = AP_RW_BOTH; + MM_int_SetPageInfo(Addr, &pi); + + memset( (void*)(Addr & ~(PAGE_SIZE-1)), 0, PAGE_SIZE ); + + return ; + } + else if( MM_GetRefCount(pi.PhysAddr) > 1 ) + { + // Duplicate the page + tPAddr newpage; + void *dst, *src; + + newpage = MM_AllocPhys(); + if(!newpage) { + Log_Error("MMVirt", "Unable to allocate new page for COW"); + for(;;); + } + dst = MM_MapTemp(newpage); + src = (void*)(Addr & ~(PAGE_SIZE-1)); + memcpy( dst, src, PAGE_SIZE ); + MM_FreeTemp( dst ); + + #if TRACE_COW + Log_Notice("MMVirt", "COW %p caused by %p, %P duped to %P (RefCnt(%i)--)", Addr, PC, + pi.PhysAddr, newpage, MM_GetRefCount(pi.PhysAddr)); + #endif + + MM_DerefPhys(pi.PhysAddr); + pi.PhysAddr = newpage; + } + #if TRACE_COW + else { + Log_Notice("MMVirt", "COW %p caused by %p, took last reference to %P", + Addr, PC, pi.PhysAddr); + } + #endif + // Unset COW + pi.AP = AP_RW_BOTH; + MM_int_SetPageInfo(Addr, &pi); + return ; + } + + + Log_Error("MMVirt", "Code at %p accessed %p (DFSR = 0x%x)%s", PC, Addr, DFSR, + (bPrefetch ? " - Prefetch" : "") + ); + if( Addr < 0x80000000 ) + MM_DumpTables(0, 0x80000000); + else + MM_DumpTables(0x80000000, -1); + for(;;); +} + diff --git a/KernelLand/Kernel/arch/armv6/pci.c b/KernelLand/Kernel/arch/armv6/pci.c new file mode 100644 index 00000000..2e674bbc --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/pci.c @@ -0,0 +1,32 @@ +/* + * + */ +#include +#include + +// Realview +//#define PCI_BASE 0x60000000 + +//#define PCI_BASE 0xF0400000 // VMM Mapping +#define PCI_BASE 0 + +// === CODE === +void PCI_CfgWriteDWord(Uint32 Addr, Uint32 Data) +{ + #if PCI_BASE + Uint32 address = PCI_BASE | Addr; + *(Uint32*)(address) = Data; + #else + #endif +} + +Uint32 PCI_CfgReadDWord(Uint32 Addr) +{ + #if PCI_BASE + Uint32 address = PCI_BASE | Addr; + return *(Uint32*)address; + #else + return 0xFFFFFFFF; + #endif +} + diff --git a/KernelLand/Kernel/arch/armv6/proc.S b/KernelLand/Kernel/arch/armv6/proc.S new file mode 100644 index 00000000..19790583 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/proc.S @@ -0,0 +1,105 @@ +/* + * Acess2 ARM + * - By John Hodge (thePowersGang) + * + * arch/arm7/proc.S + * - Process management assembly + */ + +#include "include/assembly.h" + +.globl KernelThreadHeader +@ SP+12: Argument 1 +@ SP+8: Argument Count +@ SP+4: Function +@ SP+0: Thread Pointer +KernelThreadHeader: + ldr r0, [sp],#4 + @ TODO: Do something with the thread pointer + + ldr r4, [sp],#4 @ Function + @ Get argument + ldr r0, [sp],#4 + + blx r4 + + ldr r0, =0 + bl Threads_Exit + b . + +.globl SwitchTask +@ R0: New stack +@ R1: Pointer to where to save old stack +@ R2: New IP +@ R3: Pointer to save old IP +@ SP+0: New address space +SwitchTask: + push {r4-r12,lr} + + @ Save IP + ldr r4, =.return + str r4, [r3] + @ Save SP + str sp, [r1] + + @ Only update TTBR0 if the task has an explicit address space + ldr r1, [sp,#4*10] + tst r1, r1 + mcrne p15, 0, r1, c2, c0, 0 @ Set TTBR0 to r0 +# mov r1, #1 + mcrne p15, 0, r1, c8, c7, 0 @ TLBIALL - Invalid user space + + @ Restore state + mov sp, r0 + bx r2 + +.return: + pop {r4-r12,pc} + +.extern MM_Clone +.extern MM_DumpTables +.globl Proc_CloneInt +Proc_CloneInt: + @ R0: SP Destination + @ R1: Mem Destination + push {r4-r12,lr} + mov r4, r1 @ Save mem destination + str sp, [r0] @ Save SP to SP dest + + bl MM_Clone + str r0, [r4] @ Save clone return to Mem Dest + + ldr r0, =Proc_CloneInt_new + pop {r4-r12,pc} +Proc_CloneInt_new: + mov r0, #0 + pop {r4-r12,pc} + +@ R0: New user SP +@ Return: Old user SP +.globl Proc_int_SwapUserSP +Proc_int_SwapUserSP: + cps #31 @ Go to system mode + mov r1, sp + tst r0, r0 @ Only update if non-zero + movne sp, r0 + mov r0, r1 + cps #19 + mov pc, lr + +.section .usertext, "ax" +.globl Proc_int_DropToUser +@ R0: User IP +@ R1: User SP +Proc_int_DropToUser: + cps #16 + mov sp, r1 + mov pc, r0 + +.section .rodata +csProc_CloneInt_NewTaskMessage: + .asciz "New task PC=%p, R4=%p, sp=%p" +csProc_CloneInt_OldTaskMessage: + .asciz "Parent task PC=%p, R4=%p, SP=%p" + +@ vim: ft=armv7 diff --git a/KernelLand/Kernel/arch/armv6/proc.c b/KernelLand/Kernel/arch/armv6/proc.c new file mode 100644 index 00000000..cd998f2b --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/proc.c @@ -0,0 +1,235 @@ +/* + * Acess2 + * - By John Hodge (thePowersGang) + * + * arch/arm7/proc.c + * - ARM7 Process Switching + */ +#include +#include +#include + +// === IMPORTS === +extern tThread gThreadZero; +extern tProcess gProcessZero; +extern void SwitchTask(Uint32 NewSP, Uint32 *OldSP, Uint32 NewIP, Uint32 *OldIP, Uint32 MemPtr); +extern void KernelThreadHeader(void); // Actually takes args on stack +extern void Proc_int_DropToUser(Uint32 IP, Uint32 SP) NORETURN __attribute__((long_call)); +extern Uint32 Proc_int_SwapUserSP(Uint32 NewSP); +extern Uint32 Proc_CloneInt(Uint32 *SP, Uint32 *MemPtr); +extern tVAddr MM_NewKStack(int bGlobal); // TODO: Move out into a header +extern tVAddr MM_NewUserStack(void); +extern char kernel_table0[]; + +// === PROTOTYPES === +void Proc_IdleThread(void *unused); + +// === GLOBALS === +tThread *gpCurrentThread = &gThreadZero; +tThread *gpIdleThread = NULL; + +// === CODE === +void ArchThreads_Init(void) +{ + gProcessZero.MemState.Base = (tPAddr)&kernel_table0 - KERNEL_BASE; +} + +void Proc_IdleThread(void *unused) +{ + Threads_SetPriority(gpIdleThread, -1); + for(;;) { + Proc_Reschedule(); + __asm__ __volatile__ ("wfi"); + } +} + +void Proc_Start(void) +{ + tTID tid; + + tid = Proc_NewKThread( Proc_IdleThread, NULL ); + gpIdleThread = Threads_GetThread(tid); + gpIdleThread->ThreadName = (char*)"Idle Thread"; +} + +int GetCPUNum(void) +{ + return 0; +} + +tThread *Proc_GetCurThread(void) +{ + return gpCurrentThread; +} + +void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, const char **ArgV, int DataSize) +{ + Uint32 *usr_sp; + int i; + const char **envp; + tVAddr delta; + +// Log_Debug("Proc", "Proc_StartUser: (Entrypoint=%p, Base=%p, ArgC=%i, ArgV=%p, DataSize=0x%x)", +// Entrypoint, Base, ArgC, ArgV, DataSize); + + // Write data to the user's stack + usr_sp = (void*)MM_NewUserStack(); + usr_sp -= (DataSize+3)/4; + memcpy(usr_sp, ArgV, DataSize); + free(ArgV); + + // Adjust user's copy of the arguments + delta = (tVAddr)usr_sp - (tVAddr)ArgV; + ArgV = (void*)usr_sp; + for(i = 0; ArgV[i]; i ++) ArgV[i] += delta; + envp = &ArgV[i+1]; + for(i = 0; envp[i]; i ++) envp[i] += delta; + + *--usr_sp = (Uint32)envp; + *--usr_sp = (Uint32)ArgV; + *--usr_sp = (Uint32)ArgC; + *--usr_sp = Base; + + // Drop to user code + Log_Debug("Proc", "Proc_int_DropToUser(%p, %p)", Entrypoint, usr_sp); + Proc_int_DropToUser(Entrypoint, (Uint32)usr_sp); +} + +void Proc_ClearProcess(tProcess *Process) +{ + Log_Warning("Proc", "TODO: Nuke address space etc"); +} + +void Proc_ClearThread(tThread *Thread) +{ +} + +tTID Proc_Clone(Uint Flags) +{ + tThread *new; + Uint32 pc, sp, mem; + + new = Threads_CloneTCB(Flags); + if(!new) return -1; + + // Actual clone magic + pc = Proc_CloneInt(&sp, &mem); + if(pc == 0) { + Log("Proc_Clone: In child"); + return 0; + } + + new->SavedState.IP = pc; + new->SavedState.SP = sp; + new->SavedState.UserSP = Proc_int_SwapUserSP(0); + new->SavedState.UserIP = Proc_GetCurThread()->SavedState.UserIP; + new->Process->MemState.Base = mem; + + Threads_AddActive(new); + + return new->TID; +} + +int Proc_SpawnWorker( void (*Fnc)(void*), void *Ptr ) +{ + tThread *new; + Uint32 sp; + + new = Threads_CloneThreadZero(); + if(!new) return -1; + if(new->ThreadName) free(new->ThreadName); + new->ThreadName = NULL; + + new->KernelStack = MM_NewKStack(1); + if(!new->KernelStack) { + // TODO: Delete thread + Log_Error("Proc", "Unable to allocate kernel stack"); + return -1; + } + + sp = new->KernelStack; + + *(Uint32*)(sp -= 4) = (Uint)Ptr; + *(Uint32*)(sp -= 4) = (Uint)Fnc; + *(Uint32*)(sp -= 4) = (Uint)new; + + new->SavedState.SP = sp; + new->SavedState.IP = (Uint)KernelThreadHeader; + + Threads_AddActive(new); + + return new->TID; +} + +tTID Proc_NewKThread( void (*Fnc)(void*), void *Ptr ) +{ + tThread *new; + Uint32 sp; + + new = Threads_CloneTCB(0); + if(!new) return -1; + free(new->ThreadName); + new->ThreadName = NULL; + + // TODO: Non-shared stack + new->KernelStack = MM_NewKStack(1); + if(!new->KernelStack) { + // TODO: Delete thread + Log_Error("Proc", "Unable to allocate kernel stack"); + return -1; + } + + sp = new->KernelStack; + + *(Uint32*)(sp -= 4) = (Uint)Ptr; + *(Uint32*)(sp -= 4) = (Uint)Fnc; + *(Uint32*)(sp -= 4) = (Uint)new; + + new->SavedState.SP = sp; + new->SavedState.IP = (Uint)KernelThreadHeader; + + Threads_AddActive(new); + + return new->TID; +} + +void Proc_CallFaultHandler(tThread *Thread) +{ + +} + +void Proc_Reschedule(void) +{ + tThread *cur, *next; + + cur = gpCurrentThread; + + next = Threads_GetNextToRun(0, cur); + if(!next) next = gpIdleThread; + if(!next || next == cur) return; + + Log("Switching to %p (%i %s) IP=%p SP=%p TTBR0=%p UsrSP=%p", + next, next->TID, next->ThreadName, + next->SavedState.IP, next->SavedState.SP, next->Process->MemState.Base, + next->SavedState.UserSP + ); + + Log("Requested by %p", __builtin_return_address(0)); + + gpCurrentThread = next; + + cur->SavedState.UserSP = Proc_int_SwapUserSP( next->SavedState.UserSP ); + + SwitchTask( + next->SavedState.SP, &cur->SavedState.SP, + next->SavedState.IP, &cur->SavedState.IP, + next->Process->MemState.Base + ); + +} + +void Proc_DumpThreadCPUState(tThread *Thread) +{ + +} + diff --git a/KernelLand/Kernel/arch/armv6/start.S b/KernelLand/Kernel/arch/armv6/start.S new file mode 100644 index 00000000..4be97676 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/start.S @@ -0,0 +1,370 @@ + +#include "include/assembly.h" +#include "include/options.h" + +@ +@ Exception defs taken from ARM DDI 0406B +@ +.section .init +interrupt_vector_table: +ivt_reset: b _start @ 0x00 Reset +ivt_undef: b Undef_Handler @ 0x04 #UD +ivt_svc: b SVC_Handler @ 0x08 SVC (used to be called SWI) +ivt_prefetch: b PrefetchAbort @ 0x0C Prefetch abort +ivt_data: b DataAbort @ 0x10 Data abort +ivt_unused: b . @ 0x14 Not Used +ivt_irq: b IRQHandler @ 0x18 IRQ +ivt_fiq: b . @ 0x1C FIQ (Fast interrupt) + +.globl _start +_start: + ldr r2, =UART0_PADDR + mov r1, #'A' + str r1, [r2] + + ldr r0, =kernel_table0-KERNEL_BASE + mcr p15, 0, r0, c2, c0, 1 @ Set TTBR1 to r0 + mcr p15, 0, r0, c2, c0, 0 @ Set TTBR0 to r0 too (for identity) + + mov r1, #'c' + str r1, [r2] + + mov r0, #1 + mcr p15, 0, r0, c2, c0, 2 @ Set TTCR to 1 (50/50 split) + + mov r1, #'e' + str r1, [r2] + + mov r0, #3 + mcr p15, 0, r0, c3, c0, 0 @ Set Domain 0 to Manager + + mov r1, #'s' + str r1, [r2] + + @ Enable VMSA + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #1 + orr r0, r0, #1 << 23 + mcr p15, 0, r0, c1, c0, 0 + + @ HACK: Set ASID to non zero + mov r0, #1 + MCR p15,0,r0,c13,c0,1 + + ldr r2, =0xF1000000 + mov r1, #'s' + str r1, [r2] + + @ Enable access faults on domains 0 & 1 + mov r0, #0x55 @ 01010101b + mcr p15, 0, r0, c3, c0, 0 + + mov r1, #'2' + str r1, [r2] + + @ + @ Check for security extensions + @ + mrc p15, 0, r0, c0, c1, 1 + and r0, #0xF0 + @ - Present + ldrne r0,=KERNEL_BASE + mcrne p15, 0, r0, c12, c0, 0 @ Set the VBAR (brings exceptions into high memory) + @ - Absent + mrceq p15, 0, r0, c1, c0, 0 @ Set SCTLR.V + orreq r0, #0x2000 + mcreq p15, 0, r0, c1, c0, 0 + + mov r1, #'-' + str r1, [r2] + + @ Prepare for interrupts + cps #18 @ IRQ Mode + ldr sp, =irqstack+0x1000 @ Set up stack + cps #23 @ Abort Mode + ldr sp, =abortstack+0x1000 + cps #19 + + mov r1, #'a' + str r1, [r2] + mov r1, #'r' + str r1, [r2] + mov r1, #'m' + str r1, [r2] + mov r1, #13 + str r1, [r2] + mov r1, #10 + str r1, [r2] + +.extern bss_start +.extern bss_size_div_4 +.zero_bss: + ldr r0, =bss_start + ldr r1, =bss_end + mov r3, #0 +.zero_bss_loop: + str r3, [r0],#4 + cmp r0, r1 + bls .zero_bss_loop + +.goto_c: + ldr sp, =0x80000000-8 @ Set up stack (top of user range) + ldr r0, =kmain + mov pc, r0 +1: b 1b @ Infinite loop + +.comm irqstack, 0x1000 @ ; 4KiB Stack +.comm abortstack, 0x1000 @ ; 4KiB Stack + +.extern SyscallHandler +SVC_Handler: +@ sub lr, #4 + srsdb sp!, #19 @ Save state to stack + cpsie ifa, #19 @ Ensure we're in supervisor with interrupts enabled (should already be there) + push {r0-r12} + + ldr r4, [lr,#-4] + mvn r5, #0xFF000000 + and r4, r5 + + tst r4, #0x1000 + bne .arm_specifics + + push {r4} + + mov r0, sp + ldr r4, =SyscallHandler + blx r4 + +@ ldr r0, =csSyscallPrintRetAddr +@ ldr r1, [sp,#9*4+5*4] +@ ldr r4, =Log +@ blx r4 + + pop {r2} @ errno + pop {r0,r1} @ Ret/RetHi + add sp, #2*4 @ Saved r2/r3 + + pop {r4-r12} + rfeia sp! @ Pop state (actually RFEFD) +.arm_specifics: + and r4, #0xFF + mov r0, r4 @ Number + mov r1, sp @ Arguments + + ldr r4, =ARMv7_int_HandleSyscalls + blx r4 + + add sp, #4*4 + pop {r4-r12} + rfeia sp! + + +.globl gpIRQHandler +gpIRQHandler: .long 0 +IRQ_saved_sp: .long 0 +IRQ_saved_lr: .long 0 +.globl IRQHandler +IRQHandler: + sub lr, #4 @ Adjust LR to the correct value + srsdb sp!, #19 @ Switch to supervisor mode (DDI0406B D1.6.5) (actually SRSFD) + cps #19 + + PUSH_GPRS + +@ ldr r0, =csIRQ_Tag +@ ldr r1, =csIRQ_Fmt +@ ldr r4, =Log_Debug +@ blx r4 + + @ Call the registered handler + ldr r0, gpIRQHandler + blx r0 + + @ Restore CPU state + POP_GPRS + cpsie i + rfeia sp! @ Pop state (actually RFEFD) + bx lr + +.globl DataAbort +DataAbort: + sub lr, #8 @ Adjust LR to the correct value + srsdb sp!, #23 @ Switch to supervisor mode (DDI0406B D1.6.5) (actually SRSFD) +@ cpsid ifa, #19 + PUSH_GPRS + + mov r3, #0 @ not a prefetch abort + mrc p15, 0, r2, c5, c0, 0 @ Read DFSR (Data Fault Status Register) to R2 + mrc p15, 0, r1, c6, c0, 0 @ Read DFAR (Data Fault Address Register) into R1 + mov r0, lr @ PC + ldr r4, =MM_PageFault + blx r4 + + POP_GPRS + rfeia sp! @ Pop state (actually RFEFD) + +.globl PrefetchAbort +PrefetchAbort: + sub lr, #4 @ Adjust LR to the correct value + srsdb sp!, #23 @ Switch to supervisor mode (DDI0406B D1.6.5) (actually SRSFD) +@ cpsid ifa, #19 + PUSH_GPRS + + ldr r0, =csAbort_Tag + ldr r1, =csPrefetchAbort_Fmt +# mov r2, lr + mrc p15, 0, r2, c6, c0, 2 @ Read IFAR (Instruction Fault Address Register) into R3 + mrc p15, 0, r3, c5, c0, 1 @ Read IFSR (Instruction Fault Status Register) into R3 + ldr r5, =Log_Error + blx r5 + +.loop: + wfi + b .loop +.globl Undef_Handler +Undef_Handler: + wfi + b Undef_Handler + +.globl abort +abort: + wfi + b abort + + +.section .rodata +csIRQ_Tag: +csAbort_Tag: + .asciz "ARMv7" +csIRQ_Fmt: + .asciz "IRQ" +csDataAbort_Fmt: + .asciz "Data Abort - %p accessed %p, DFSR=%x Unk:%x Unk:%x" +csPrefetchAbort_Fmt: + .asciz "Prefetch Abort at %p, IFSR=%x" +csSyscallPrintRetAddr: + .asciz "Syscall ret to %p" + +.section .padata +.globl kernel_table0 + +kernel_table0: + .long 0x00000402 @ Identity map the first 1 MiB + .rept 0x7FC - 1 + .long 0 + .endr + .long user_table1_map + 0x000 - KERNEL_BASE + 1 @ 0x7FC00000 + .long user_table1_map + 0x400 - KERNEL_BASE + 1 @ 0x7FD00000 + .long user_table1_map + 0x800 - KERNEL_BASE + 1 @ KStacks + .long user_table1_map + 0xC00 - KERNEL_BASE + 1 + @ 0x80000000 - User/Kernel split + .long 0x00000402 @ Map first 4 MiB to 2GiB (KRW only) + .long 0x00100402 @ + .long 0x00200402 @ + .long 0x00300402 @ + .rept 0xF00 - 0x800 - 4 + .long 0 + .endr +#if PCI_PADDR + .long PCI_PADDR + 0*(1 << 20) + 0x402 @ Map PCI config space + .long PCI_PADDR + 1*(1 << 20) + 0x402 + .long PCI_PADDR + 2*(1 << 20) + 0x402 + .long PCI_PADDR + 3*(1 << 20) + 0x402 + .long PCI_PADDR + 4*(1 << 20) + 0x402 + .long PCI_PADDR + 5*(1 << 20) + 0x402 + .long PCI_PADDR + 6*(1 << 20) + 0x402 + .long PCI_PADDR + 7*(1 << 20) + 0x402 + .long PCI_PADDR + 8*(1 << 20) + 0x402 + .long PCI_PADDR + 9*(1 << 20) + 0x402 + .long PCI_PADDR + 10*(1 << 20) + 0x402 + .long PCI_PADDR + 11*(1 << 20) + 0x402 + .long PCI_PADDR + 12*(1 << 20) + 0x402 + .long PCI_PADDR + 13*(1 << 20) + 0x402 + .long PCI_PADDR + 14*(1 << 20) + 0x402 + .long PCI_PADDR + 15*(1 << 20) + 0x402 +#else + .rept 16 + .long 0 + .endr +#endif + .long hwmap_table_0 + 0x000 - KERNEL_BASE + 1 + .long hwmap_table_0 + 0x400 - KERNEL_BASE + 1 + .long hwmap_table_0 + 0x800 - KERNEL_BASE + 1 + .long hwmap_table_0 + 0xC00 - KERNEL_BASE + 1 + .rept 0xFF8 - 0xF00 - 16 - 4 + .long 0 + .endr + @ Page fractals + .long kernel_table1_map + 0x000 - KERNEL_BASE + 1 + .long kernel_table1_map + 0x400 - KERNEL_BASE + 1 + .long kernel_table1_map + 0x800 - KERNEL_BASE + 1 + .long kernel_table1_map + 0xC00 - KERNEL_BASE + 1 + .long kernel_exception_map + 0x000 - KERNEL_BASE + 1 + .long kernel_exception_map + 0x400 - KERNEL_BASE + 1 + .long kernel_exception_map + 0x800 - KERNEL_BASE + 1 + .long kernel_exception_map + 0xC00 - KERNEL_BASE + 1 + +@ PID0 user table +.globl user_table1_map +@ User table1 data table (only the first half is needed) +@ - Abused to provide kernel stacks in the unused half of the table +user_table1_map: @ Size = 4KiB (only 2KiB used) + .rept 0x800/4-1 + .long 0 + .endr + .long user_table1_map - KERNEL_BASE + 0x13 @ ...1FF000 = 0x7FDFF000 + @ Kernel stack zone + .long kernel_table0 + 0x0000 - KERNEL_BASE + 0x13 @ ...200000 = 0x7FE00000 + .long kernel_table0 + 0x1000 - KERNEL_BASE + 0x13 @ ...201000 = 0x7FE01000 + .rept (0x800/4)-(MM_KSTACK_SIZE/0x1000)-2 + .long 0 + .endr + #if MM_KSTACK_SIZE != 0x2000 + #error Kernel stack size not changed in start.S + #endif + .long stack + 0x0000 - KERNEL_BASE + 0x13 @ Kernel Stack + .long stack + 0x1000 - KERNEL_BASE + 0x13 @ + +.globl kernel_table1_map +kernel_table1_map: @ Size = 4KiB + .rept (0xF00+16)/4 + .long 0 + .endr + .long hwmap_table_0 - KERNEL_BASE + 0x13 + .rept 0xFF8/4 - (0xF00+16)/4 - 1 + .long 0 + .endr + .long kernel_table1_map - KERNEL_BASE + 0x13 + .long kernel_exception_map - KERNEL_BASE + 0x13 + +@ Hardware mappings +.globl hwmap_table_0 +hwmap_table_0: + .long UART0_PADDR + 0x13 @ UART0 + .rept 1024 - 1 + .long 0 + .endr +.globl kernel_exception_map +kernel_exception_map: + @ Padding + .rept 1024-256 + .long 0 + .endr + @ Align to nearly the end + .rept 256-16 + .long 0 + .endr + .long 0x212 @ Map first page for exceptions (Kernel RO, Execute) + .rept 16-1-2 + .long 0 + .endr + .long gUsertextPhysStart + 0x22 @ User .text (User RO, Kernel RW, because both is COW) + .long 0 + +.section .padata +stack: + .space MM_KSTACK_SIZE, 0 @ Original kernel stack + +// vim: ts=8 ft=armv7 + diff --git a/KernelLand/Kernel/arch/armv6/time.c b/KernelLand/Kernel/arch/armv6/time.c new file mode 100644 index 00000000..d4ae4fa6 --- /dev/null +++ b/KernelLand/Kernel/arch/armv6/time.c @@ -0,0 +1,16 @@ +/* + * Acess2 + * + * ARM7 Time code + * arch/arm7/time.c + */ +#include + +// === GLOBALS === +tTime giTimestamp; + +// === CODE === +tTime now(void) +{ + return giTimestamp; +} diff --git a/KernelLand/Kernel/arch/x86/mm_phys.c b/KernelLand/Kernel/arch/x86/mm_phys.c index b0f1c616..f785ba45 100644 --- a/KernelLand/Kernel/arch/x86/mm_phys.c +++ b/KernelLand/Kernel/arch/x86/mm_phys.c @@ -152,7 +152,6 @@ void MM_DumpStatistics(void) */ tPAddr MM_AllocPhys(void) { - // int a, b, c; int indx = -1; tPAddr ret; @@ -161,7 +160,6 @@ tPAddr MM_AllocPhys(void) Mutex_Acquire( &glPhysAlloc ); // Classful scan - #if 1 { int i; int first, last; @@ -202,52 +200,6 @@ tPAddr MM_AllocPhys(void) // Out of memory? if( i <= 1 ) indx = -1; } - #elif 0 - // Find free page - // Scan downwards - LOG("giLastPossibleFree = %i", giLastPossibleFree); - for( indx = giLastPossibleFree; indx >= 0; ) - { - if( gaSuperBitmap[indx>>10] == -1 ) { - indx -= 1024; - continue; - } - - if( gaPageBitmap[indx>>5] == -1 ) { - indx -= 32; - continue; - } - - if( gaPageBitmap[indx>>5] & (1 << (indx&31)) ) { - indx --; - continue; - } - break; - } - if( indx >= 0 ) - giLastPossibleFree = indx; - LOG("indx = %i", indx); - #else - c = giLastPossibleFree % 32; - b = (giLastPossibleFree / 32) % 32; - a = giLastPossibleFree / 1024; - - LOG("a=%i,b=%i,c=%i", a, b, c); - for( ; gaSuperBitmap[a] == -1 && a >= 0; a-- ); - if(a < 0) { - Mutex_Release( &glPhysAlloc ); - Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p) - %lli/%lli used", - __builtin_return_address(0), giPhysAlloc, giPageCount); - LEAVE('i', 0); - return 0; - } - for( ; gaSuperBitmap[a] & (1<= 0 ) - giLastPossibleFree = indx; - #endif if( indx < 0 ) { Mutex_Release( &glPhysAlloc ); @@ -330,29 +282,6 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) idx = sidx / 32; sidx %= 32; - #if 0 - LOG("a=%i, b=%i, idx=%i, sidx=%i", a, b, idx, sidx); - - // Find free page - for( ; gaSuperBitmap[a] == -1 && a --; ) b = 31; - if(a < 0) { - Mutex_Release( &glPhysAlloc ); - Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0)); - LEAVE('i', 0); - return 0; - } - LOG("a = %i", a); - for( ; gaSuperBitmap[a] & (1 << b); b-- ) sidx = 31; - LOG("b = %i", b); - idx = a * 32 + b; - for( ; gaPageBitmap[idx] & (1 << sidx); sidx-- ) - LOG("gaPageBitmap[%i] = 0x%08x", idx, gaPageBitmap[idx]); - - LOG("idx = %i, sidx = %i", idx, sidx); - #else - - #endif - // Check if the gap is large enough while( idx >= 0 ) { diff --git a/KernelLand/Kernel/arch/x86_64/errors.c b/KernelLand/Kernel/arch/x86_64/errors.c index f7da7f9f..e7812c3e 100644 --- a/KernelLand/Kernel/arch/x86_64/errors.c +++ b/KernelLand/Kernel/arch/x86_64/errors.c @@ -134,14 +134,14 @@ void Error_Backtrace(Uint IP, Uint BP) LogF("Backtrace: %p", IP); //else // LogF("Backtrace: %s+0x%x", str, delta); - if( !MM_GetPhysAddr(BP) ) + if( !MM_GetPhysAddr( (void*)BP ) ) { LogF("\nBacktrace: Invalid BP, stopping\n"); return; } - while( MM_GetPhysAddr(BP) && MM_GetPhysAddr(BP+8+7) && i < MAX_BACKTRACE ) + while( MM_GetPhysAddr( (void*)BP) && MM_GetPhysAddr((void*)(BP+8+7)) && i < MAX_BACKTRACE ) { //str = Debug_GetSymbol(*(Uint*)(ebp+4), &delta); //if(str == NULL) diff --git a/KernelLand/Kernel/arch/x86_64/main.c b/KernelLand/Kernel/arch/x86_64/main.c index 3532c809..cefeeb47 100644 --- a/KernelLand/Kernel/arch/x86_64/main.c +++ b/KernelLand/Kernel/arch/x86_64/main.c @@ -5,13 +5,14 @@ #include #include +// === CONSTANTS === +#define MAX_PMEMMAP_ENTS 16 + // === IMPORTS === extern void Desctab_Init(void); extern void MM_InitVirt(void); extern void Heap_Install(void); -extern void Threads_Init(void); extern int Time_Setup(void); -extern void System_Init(char *Commandline); extern void MM_InitPhys_Multiboot(tMBoot_Info *MBoot); @@ -26,8 +27,7 @@ void kmain(Uint MbMagic, void *MbInfoPtr) { tMBoot_Info *mbInfo; - LogF("Acess2 x86_64 v"EXPAND_STR(KERNEL_VERSION)"\n"); - LogF(" Build %i, Git Hash %s\n", BUILD_NUM, gsGitHash); + LogF("%s\r\n", gsBuildInfo); Desctab_Init(); diff --git a/KernelLand/Kernel/arch/x86_64/mm_phys.c b/KernelLand/Kernel/arch/x86_64/mm_phys.c index 274b21c7..b537a9f4 100644 --- a/KernelLand/Kernel/arch/x86_64/mm_phys.c +++ b/KernelLand/Kernel/arch/x86_64/mm_phys.c @@ -440,7 +440,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) for( i = 0; i < Pages; i++, addr++ ) { gaMainBitmap[addr >> 6] |= 1LL << (addr & 63); - if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[addr] ) ) + if( MM_GetPhysAddr( &gaiPageReferences[addr] ) ) gaiPageReferences[addr] = 1; // Log("page %P refcount = %i", MM_GetRefCount(addr<<12)); rangeID = MM_int_GetRangeID(addr << 12); @@ -504,7 +504,7 @@ void MM_RefPhys(tPAddr PAddr) { tVAddr ref_base = ((tVAddr)&gaiPageReferences[ page ]) & ~0xFFF; // Allocate reference page - if( !MM_GetPhysAddr(ref_base) ) + if( !MM_GetPhysAddr(&gaiPageReferences[page]) ) { const int pages_per_refpage = PAGE_SIZE/sizeof(gaiPageReferences[0]); int i; @@ -528,7 +528,7 @@ void MM_RefPhys(tPAddr PAddr) PAGE_ALLOC_SET(page); if( gaMainBitmap[page >> 6] + 1 == 0 ) gaSuperBitmap[page>> 12] |= 1LL << ((page >> 6) & 63); - if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[page] ) ) + if( MM_GetPhysAddr( &gaiPageReferences[page] ) ) gaiPageReferences[page] = 1; } @@ -546,7 +546,7 @@ void MM_DerefPhys(tPAddr PAddr) if( PAddr >> 12 > giMaxPhysPage ) return ; - if( MM_GetPhysAddr( (tVAddr) &gaiPageReferences[page] ) ) + if( MM_GetPhysAddr( &gaiPageReferences[page] ) ) { gaiPageReferences[ page ] --; if( gaiPageReferences[ page ] == 0 ) @@ -583,7 +583,7 @@ int MM_GetRefCount( tPAddr PAddr ) if( PAddr > giMaxPhysPage ) return 0; - if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[PAddr] ) ) { + if( MM_GetPhysAddr( &gaiPageReferences[PAddr] ) ) { return gaiPageReferences[PAddr]; } @@ -620,7 +620,7 @@ int MM_SetPageNode(tPAddr PAddr, void *Node) // if( !MM_GetRefCount(PAddr) ) return 1; - if( !MM_GetPhysAddr(node_page) ) { + if( !MM_GetPhysAddr((void*)node_page) ) { if( !MM_Allocate(node_page) ) return -1; memset( (void*)node_page, 0, PAGE_SIZE ); @@ -635,7 +635,7 @@ int MM_GetPageNode(tPAddr PAddr, void **Node) // if( !MM_GetRefCount(PAddr) ) return 1; PAddr >>= 12; - if( !MM_GetPhysAddr( (tVAddr)&gapPageNodes[PAddr] ) ) { + if( !MM_GetPhysAddr( &gapPageNodes[PAddr] ) ) { *Node = NULL; return 0; } diff --git a/KernelLand/Kernel/arch/x86_64/mm_virt.c b/KernelLand/Kernel/arch/x86_64/mm_virt.c index 3d723e19..14117f48 100644 --- a/KernelLand/Kernel/arch/x86_64/mm_virt.c +++ b/KernelLand/Kernel/arch/x86_64/mm_virt.c @@ -269,9 +269,9 @@ void MM_int_DumpTablesEnt(tVAddr RangeStart, size_t Length, tPAddr Expected) #define CANOICAL(addr) ((addr)&0x800000000000?(addr)|0xFFFF000000000000:(addr)) LogF("%016llx => ", CANOICAL(RangeStart)); // LogF("%6llx %6llx %6llx %016llx => ", -// MM_GetPhysAddr( (tVAddr)&PAGEDIRPTR(RangeStart>>30) ), -// MM_GetPhysAddr( (tVAddr)&PAGEDIR(RangeStart>>21) ), -// MM_GetPhysAddr( (tVAddr)&PAGETABLE(RangeStart>>12) ), +// MM_GetPhysAddr( &PAGEDIRPTR(RangeStart>>30) ), +// MM_GetPhysAddr( &PAGEDIR(RangeStart>>21) ), +// MM_GetPhysAddr( &PAGETABLE(RangeStart>>12) ), // CANOICAL(RangeStart) // ); if( gMM_ZeroPage && (PAGETABLE(RangeStart>>12) & PADDR_MASK) == gMM_ZeroPage ) @@ -576,7 +576,7 @@ void MM_Deallocate(tVAddr VAddr) { tPAddr phys; - phys = MM_GetPhysAddr(VAddr); + phys = MM_GetPhysAddr( (void*)VAddr ); if(!phys) return ; MM_Unmap(VAddr); @@ -609,8 +609,9 @@ int MM_GetPageEntry(tVAddr Addr, tPAddr *Phys, Uint *Flags) /** * \brief Get the physical address of a virtual location */ -tPAddr MM_GetPhysAddr(tVAddr Addr) +tPAddr MM_GetPhysAddr(const void *Ptr) { + tVAddr Addr = (tVAddr)Ptr; tPAddr *ptr; int ret; @@ -776,7 +777,8 @@ tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) { for( num = Number; num -- && ret < MM_HWMAP_TOP; ret += 0x1000 ) { - if( MM_GetPhysAddr(ret) != 0 ) break; + if( MM_GetPhysAddr( (void*)ret ) != 0 ) + break; } if( num >= 0 ) continue; @@ -807,7 +809,7 @@ void MM_UnmapHWPages(tVAddr VAddr, Uint Number) // Log_KernelPanic("MM", "TODO: Implement MM_UnmapHWPages"); while( Number -- ) { - MM_DerefPhys( MM_GetPhysAddr(VAddr) ); + MM_DerefPhys( MM_GetPhysAddr((void*)VAddr) ); MM_Unmap(VAddr); VAddr += 0x1000; } @@ -970,7 +972,7 @@ tPAddr MM_Clone(void) MM_MapEx(kstackbase+i*0x1000, phys, 1, 0); tmpmapping = MM_MapTemp(phys); - if( MM_GetPhysAddr( kstackbase+i*0x1000 ) ) + if( MM_GetPhysAddr( (void*)(kstackbase+i*0x1000) ) ) memcpy(tmpmapping, (void*)(kstackbase+i*0x1000), 0x1000); else memset(tmpmapping, 0, 0x1000); @@ -1088,7 +1090,7 @@ tVAddr MM_NewKStack(void) Uint i; for( ; base < MM_KSTACK_TOP; base += KERNEL_STACK_SIZE ) { - if(MM_GetPhysAddr(base+KERNEL_STACK_SIZE-0x1000) != 0) + if(MM_GetPhysAddr( (void*)(base+KERNEL_STACK_SIZE-0x1000) ) != 0) continue; //Log("MM_NewKStack: Found one at %p", base + KERNEL_STACK_SIZE); diff --git a/KernelLand/Kernel/arch/x86_64/proc.c b/KernelLand/Kernel/arch/x86_64/proc.c index 5f71a45f..518bef3a 100644 --- a/KernelLand/Kernel/arch/x86_64/proc.c +++ b/KernelLand/Kernel/arch/x86_64/proc.c @@ -579,7 +579,7 @@ Uint Proc_MakeUserStack(void) // Check Prospective Space for( i = USER_STACK_SZ >> 12; i--; ) { - if( MM_GetPhysAddr( base + (i<<12) ) != 0 ) + if( MM_GetPhysAddr( (void*)(base + (i<<12)) ) != 0 ) break; } diff --git a/KernelLand/Kernel/arch/x86_64/start32.asm b/KernelLand/Kernel/arch/x86_64/start32.asm index 52b133c6..ac059711 100644 --- a/KernelLand/Kernel/arch/x86_64/start32.asm +++ b/KernelLand/Kernel/arch/x86_64/start32.asm @@ -183,6 +183,6 @@ gInitialKernelStack: [section .rodata] csNot64BitCapable: - db "Not 64-bit Capable",0 + db "CPU does not support long-mode, please use the x86 build",0 ; vim: ft=nasm diff --git a/KernelLand/Kernel/drvutil_video.c b/KernelLand/Kernel/drvutil_video.c index 05fa1026..2bee791f 100644 --- a/KernelLand/Kernel/drvutil_video.c +++ b/KernelLand/Kernel/drvutil_video.c @@ -265,12 +265,16 @@ int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t px = (void*)dest; } } + if( x > 0 ) { + dest += FBInfo->Pitch; + } } else { ofs = Offset; dest += ofs; memcpy(dest, Buffer, Length); + dest += Length; } break; default: @@ -293,9 +297,11 @@ int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t return -1; } if( FBInfo->BackBuffer && dest ) { - memcpy((char*)FBInfo->Framebuffer + ofs, (char*)FBInfo->BackBuffer + ofs, - ((tVAddr)dest - (tVAddr)FBInfo->BackBuffer) - ofs - ); + void *_dst = (char*)FBInfo->Framebuffer + ofs; + void *_src = (char*)FBInfo->BackBuffer + ofs; + size_t len = ((tVAddr)dest - (tVAddr)FBInfo->BackBuffer) - ofs; + // Log_Debug("DrvUtil", "Copy from BB %p to FB %p 0x%x bytes", _src, _dst, len); + memcpy(_dst, _src, len); } DrvUtil_Video_DrawCursor(FBInfo, csr_x, csr_y); diff --git a/KernelLand/Kernel/include/tpl_mm_phys_bitmap.h b/KernelLand/Kernel/include/tpl_mm_phys_bitmap.h index cf3018f0..005a2f8c 100644 --- a/KernelLand/Kernel/include/tpl_mm_phys_bitmap.h +++ b/KernelLand/Kernel/include/tpl_mm_phys_bitmap.h @@ -83,7 +83,7 @@ void MM_Tpl_InitPhys(int MaxRAMPage, void *MemoryMap) bitmap_page &= ~(PAGE_SIZE-1); // Only need to allocate bitmaps - if( !MM_GetPhysAddr( bitmap_page ) ) { + if( !MM_GetPhysAddr( (void*)bitmap_page ) ) { if( !MM_Allocate( bitmap_page ) ) { Log_KernelPanic("PMM", "Out of memory during init, this is bad"); return ; @@ -220,7 +220,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) LOG("if( MM_GetPhysAddr( %p ) )", &gaiPageReferences[addr]); // Mark as referenced if the reference count page is valid - if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[addr] ) ) { + if( MM_GetPhysAddr( &gaiPageReferences[addr] ) ) { gaiPageReferences[addr] = 1; } } @@ -276,7 +276,7 @@ tPAddr MM_AllocPhys(void) tPAddr ret = 0; for( ret = 0; ret < giMaxPhysPage; ret ++ ) { - if( !MM_GetPhysAddr( (tVAddr)&gaPageBitmaps[ret/32] ) ) { + if( !MM_GetPhysAddr( &gaPageBitmaps[ret/32] ) ) { ret += PAGE_SIZE*8; continue ; } @@ -317,13 +317,13 @@ void MM_RefPhys(tPAddr PAddr) if( gaPageBitmaps[page / 32] == 0 ) gaSuperBitmap[page / (32*32)] &= ~(1LL << ((page / 32) & 31)); #endif - if( MM_GetPhysAddr( refpage ) ) + if( MM_GetPhysAddr( (void*)refpage ) ) gaiPageReferences[page] = 1; } else { // Reference again - if( !MM_GetPhysAddr( refpage ) ) + if( !MM_GetPhysAddr( (void*)refpage ) ) { int pages_per_page, basepage, i; if( MM_Allocate(refpage) == 0 ) { @@ -350,7 +350,7 @@ void MM_RefPhys(tPAddr PAddr) int MM_GetRefCount(tPAddr PAddr) { PAddr >>= 12; - if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[PAddr] ) ) { + if( MM_GetPhysAddr( &gaiPageReferences[PAddr] ) ) { return gaiPageReferences[PAddr]; } @@ -372,7 +372,7 @@ void MM_DerefPhys(tPAddr PAddr) ENTER("PPAddr", PAddr); - if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[page] ) ) + if( MM_GetPhysAddr( &gaiPageReferences[page] ) ) { if( gaiPageReferences[page] > 0 ) gaiPageReferences[ page ] --; @@ -384,7 +384,7 @@ void MM_DerefPhys(tPAddr PAddr) else gaPageBitmaps[ page / 32 ] |= 1 << (page&31); // Clear node if needed - if( MM_GetPhysAddr( (tVAddr)&gapPageNodes[page] ) ) { + if( MM_GetPhysAddr( &gapPageNodes[page] ) ) { gapPageNodes[page] = NULL; // TODO: Catch when all pages in this range are not using nodes } @@ -415,7 +415,7 @@ int MM_SetPageNode(tPAddr PAddr, void *Node) if( !MM_GetRefCount(PAddr) ) return 1; - if( !MM_GetPhysAddr(node_page) ) { + if( !MM_GetPhysAddr( (void*)node_page ) ) { if( !MM_Allocate(node_page) ) return -1; memset( (void*)node_page, 0, PAGE_SIZE ); @@ -430,7 +430,7 @@ int MM_GetPageNode(tPAddr PAddr, void **Node) if( !MM_GetRefCount(PAddr) ) return 1; PAddr >>= 12; - if( !MM_GetPhysAddr( (tVAddr)&gapPageNodes[PAddr] ) ) { + if( !MM_GetPhysAddr( &gapPageNodes[PAddr] ) ) { *Node = NULL; return 0; } diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c index 60996211..17cccca1 100644 --- a/KernelLand/Kernel/threads.c +++ b/KernelLand/Kernel/threads.c @@ -504,15 +504,13 @@ tThread *Threads_GetThread(Uint TID) tThread *thread; // Search global list - for(thread = gAllThreads; - thread; - thread = thread->GlobalNext) + for( thread = gAllThreads; thread; thread = thread->GlobalNext ) { if(thread->TID == TID) return thread; } - Log("Unable to find TID %i on main list\n", TID); + Log_Notice("Threads", "Unable to find TID %i on main list\n", TID); return NULL; } diff --git a/KernelLand/Kernel/vfs/io.c b/KernelLand/Kernel/vfs/io.c index dacf720e..7379e3d2 100644 --- a/KernelLand/Kernel/vfs/io.c +++ b/KernelLand/Kernel/vfs/io.c @@ -38,6 +38,12 @@ Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer) LOG("No read method"); LEAVE_RET('i', -1); } + + if( !MM_GetPhysAddr(h->Node->Type->Read) ) { + Log_Error("VFS", "Node type %p(%s) read method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName, + h->Node->Type->Read); + LEAVE_RET('i', -1); + } ret = h->Node->Type->Read(h->Node, h->Position, Length, Buffer); if(ret == -1) LEAVE_RET('i', -1); @@ -66,6 +72,13 @@ Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer) Warning("VFS_ReadAt - Node %p, does not have a read method", h->Node); return 0; } + + if( !MM_GetPhysAddr(h->Node->Type->Read) ) { + Log_Error("VFS", "Node type %p(%s) read method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName, + h->Node->Type->Read); + LEAVE_RET('i', -1); + } + ret = h->Node->Type->Read(h->Node, Offset, Length, Buffer); if(ret == -1) return -1; return ret; @@ -87,6 +100,12 @@ Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer) if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1; if( !h->Node->Type || !h->Node->Type->Write ) return 0; + + if( !MM_GetPhysAddr(h->Node->Type->Write) ) { + Log_Error("VFS", "Node type %p(%s) write method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName, + h->Node->Type->Write); + return -1; + } ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer); if(ret == -1) return -1; @@ -111,8 +130,13 @@ Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer) if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1; if(!h->Node->Type || !h->Node->Type->Write) return 0; - ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer); + if( !MM_GetPhysAddr(h->Node->Type->Write) ) { + Log_Error("VFS", "Node type %p(%s) write method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName, + h->Node->Type->Write); + return -1; + } + ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer); if(ret == -1) return -1; return ret; } diff --git a/KernelLand/Kernel/vfs/open.c b/KernelLand/Kernel/vfs/open.c index 344b2a14..983a2b23 100644 --- a/KernelLand/Kernel/vfs/open.c +++ b/KernelLand/Kernel/vfs/open.c @@ -702,7 +702,7 @@ int VFS_ChDir(const char *Dest) *cwdptr = buf; } - Log("Updated CWD to '%s'", buf); + Log_Debug("VFS", "Updated CWD to '%s'", buf); return 1; } diff --git a/KernelLand/Kernel/vfs/select.c b/KernelLand/Kernel/vfs/select.c index c34700c8..412cb1ae 100644 --- a/KernelLand/Kernel/vfs/select.c +++ b/KernelLand/Kernel/vfs/select.c @@ -402,6 +402,7 @@ int VFS_int_Select_AddThread(tVFS_SelectList *List, tThread *Thread, int MaxAllo } count ++; if( MaxAllowed && count >= MaxAllowed ) { + Mutex_Release(&List->Lock); LEAVE('i', 1); return 1; } diff --git a/KernelLand/Modules/Display/Tegra2Vid/main.c b/KernelLand/Modules/Display/Tegra2Vid/main.c index 523cecce..e19a5ff7 100644 --- a/KernelLand/Modules/Display/Tegra2Vid/main.c +++ b/KernelLand/Modules/Display/Tegra2Vid/main.c @@ -116,15 +116,26 @@ int Tegra2Vid_Install(char **Arguments) ); memset(gpTegra2Vid_Framebuffer, 0xFF, 0x1000); -// gpTegra2Vid_IOMem[DC_WIN_A_WIN_OPTIONS_0] = (1 << 30); -// gpTegra2Vid_IOMem[DC_WIN_A_COLOR_DEPTH_0] = 12; // Could be 13 (BGR/RGB) -// gpTegra2Vid_IOMem[DC_WIN_A_PRESCALED_SIZE_0] = gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]; - gpTegra2Vid_IOMem[DC_WIN_A_LINE_STRIDE_0] = 1024*2; +#if 0 + gpTegra2Vid_IOMem[DC_WIN_A_WIN_OPTIONS_0] = (1 << 30); + gpTegra2Vid_IOMem[DC_WIN_A_COLOR_DEPTH_0] = 12; // Could be 13 (BGR/RGB) + gpTegra2Vid_IOMem[DC_WIN_A_PRESCALED_SIZE_0] = gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]; + gpTegra2Vid_IOMem[DC_WIN_A_LINE_STRIDE_0] = + gTegra2Vid_DrvUtil_BufInfo.Pitch = + 1680*4; + gTegra2Vid_DrvUtil_BufInfo.Depth = 32; + gTegra2Vid_DrvUtil_BufInfo.Width = 1680; + gTegra2Vid_DrvUtil_BufInfo.Height = 1050; +#else + gpTegra2Vid_IOMem[DC_WIN_A_COLOR_DEPTH_0] = 13; // Could be 13 (BGR/RGB) + gpTegra2Vid_IOMem[DC_WIN_A_LINE_STRIDE_0] = + gTegra2Vid_DrvUtil_BufInfo.Pitch = 1024*4; + gTegra2Vid_DrvUtil_BufInfo.Depth = 32; gTegra2Vid_DrvUtil_BufInfo.Width = 1024; gTegra2Vid_DrvUtil_BufInfo.Height = 768; - gTegra2Vid_DrvUtil_BufInfo.Pitch = 1024*2; - gTegra2Vid_DrvUtil_BufInfo.Depth = 16; gTegra2Vid_DrvUtil_BufInfo.Framebuffer = gpTegra2Vid_Framebuffer; +#endif + gpTegra2Vid_IOMem[DC_CMD_STATE_CONTROL_0] = WIN_A_ACT_REQ; // Tegra2Vid_int_SetMode(4); @@ -307,16 +318,16 @@ 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 - *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_FRONT_PORCH_0) = (mode->VFP << 16) | mode->HFP; - *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_SYNC_WIDTH_0) = (mode->HS << 16) | mode->HS; - *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_BACK_PORCH_0) = (mode->VBP << 16) | mode->HBP; - *(Uint32*)(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_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; - *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_POSITION_0) = 0; - *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_SIZE_0) = (h << 16) | w; - *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_COLOR_CONTROL_0) = 0x8; // BASE888 - *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_COLOR_DEPTH_0) = 12; // Could be 13 (BGR/RGB) - *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_PRESCALED_SIZE_0) = (h << 16) | w; + 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; Log_Debug("Tegra2Vid", "Mode %i (%ix%i) selected", Mode, w, h); @@ -329,6 +340,7 @@ int Tegra2Vid_int_SetMode(int Mode) giTegra2Vid_FramebufferSize = w*h*4; + // TODO: Does this need RAM or unmapped space? gpTegra2Vid_Framebuffer = (void*)MM_AllocDMA( (giTegra2Vid_FramebufferSize + PAGE_SIZE-1) / PAGE_SIZE, 32, @@ -342,10 +354,12 @@ int Tegra2Vid_int_SetMode(int Mode) ); // Tell hardware - *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_START_ADDR_0) = gTegra2Vid_FramebufferPhys; - *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_V_OFFSET_0) = 0; // Y offset - *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_H_OFFSET_0) = 0; // X offset + gpTegra2Vid_IOMem[DC_WINBUF_A_START_ADDR_0] = gTegra2Vid_FramebufferPhys; + gpTegra2Vid_IOMem[DC_WINBUF_A_ADDR_V_OFFSET_0] = 0; // Y offset + gpTegra2Vid_IOMem[DC_WINBUF_A_ADDR_H_OFFSET_0] = 0; // X offset } + gpTegra2Vid_IOMem[DC_CMD_STATE_CONTROL_0] = WIN_A_ACT_REQ; + return 0; } diff --git a/KernelLand/Modules/Display/Tegra2Vid/tegra2.h b/KernelLand/Modules/Display/Tegra2Vid/tegra2.h index 69b9dc2f..7e3fdf5c 100644 --- a/KernelLand/Modules/Display/Tegra2Vid/tegra2.h +++ b/KernelLand/Modules/Display/Tegra2Vid/tegra2.h @@ -356,5 +356,14 @@ const char * const csaTegra2Vid_RegisterNames[] = { }; #endif +// Bit definitions +/// \name DC_CMD_STATE_CONTROL_0 +/// \{ +#define GEN_ACT_REQ 0x0001 +#define WIN_A_ACT_REQ 0x0002 +#define WIN_B_ACT_REQ 0x0004 +#define WIN_C_ACT_REQ 0x0008 +/// \} + #endif diff --git a/KernelLand/Modules/IPStack/adapters.c b/KernelLand/Modules/IPStack/adapters.c index 58e503c0..16e0f975 100644 --- a/KernelLand/Modules/IPStack/adapters.c +++ b/KernelLand/Modules/IPStack/adapters.c @@ -344,7 +344,9 @@ void IPStack_SendDebugText(const char *Text) if( CPU_HAS_LOCK(&lLock) ) return ; // Nested! SHORTLOCK(&lLock); -// __asm__ __volatile__ ("sti"); // Start interrupts (x86 specific) + #if ARCHDIR_is_x86 + __asm__ __volatile__ ("sti"); // Start interrupts (x86 specific) + #endif // Cache packets until a newline static char cache[1500 - (sizeof(pkt_hdr) + 4)]; diff --git a/KernelLand/Modules/Makefile.tpl b/KernelLand/Modules/Makefile.tpl index 6c6611e0..19fd77ea 100644 --- a/KernelLand/Modules/Makefile.tpl +++ b/KernelLand/Modules/Makefile.tpl @@ -13,7 +13,7 @@ CPPFLAGS := -I$(ACESSDIR)/KernelLand/Kernel/include -I$(ACESSDIR)/KernelLand/Ker CPPFLAGS += -I$(ACESSDIR)/KernelLand/Modules CPPFLAGS += -DARCH=$(ARCH) -DARCH_is_$(ARCH) -DARCHDIR_is_$(ARCHDIR) CPPFLAGS += $(_CPPFLAGS) -CPPFLAGS += $(LIBINCLUDES) +CPPFLAGS += $(LIBINCLUDES) -ffreestanding CFLAGS := -std=gnu99 -Wall -fno-stack-protector -g -O3 CFLAGS += -Werror diff --git a/Makefile.cfg b/Makefile.cfg index 14d5065f..7b0ad8c3 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -51,6 +51,7 @@ endif DRIVERS := MODULES := +MODULES += Filesystems/RAMDisk MODULES += Filesystems/Ext2 MODULES += Filesystems/FAT MODULES += Filesystems/NTFS diff --git a/Notes/SIF.txt b/Notes/SIF.txt new file mode 100644 index 00000000..57c1fa7e --- /dev/null +++ b/Notes/SIF.txt @@ -0,0 +1,28 @@ +=== Simple Image Format === + +U16 Magic 0x51F0 - This determines the endianness of the file +U16 Flags + > 0-2: Compression (0: Uncompressed, 1: RLE, 2: zlib, 3: RLE-Channel) + > 3-5: Format (0: ARGB, 1: RGB +U16 Width +U16 Height + + + +=== Compression Formats === +0 - Uncompressed + The file data is a linear sequence of Width * Height 32-bit ARGB + words (in file endianness, determined by the magic) + +1 - RLE-4 + 7-bit length followed by a 32-bit value that is repeated `n` times + (if bit 7 of the length byte is set, the next `n` 32-bit words are + verbatim) + +2 - zlib + The image data is a zlib stream of 32-bit xRGB words + +3 - RLE-Channel + The data is the alpha values, followed by red, then green, then blue + encoded as RLE with a 7-bit length and a verbatim flag (same as mode + 1, except with 8-bit values instead of 32-bit) diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 00000000..f6c8efa9 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,56 @@ +TODO: +- E1000 Driver (stubbed) + > Find specs + http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf + > Use bochs/qemu only as a backup + +- Cirrus 64-bit VisualMedia Accelerator + PCI 1013:00B8 (Cirrus CLGD5446) + > Specs avail? + Qemu Suggests http://home.worldonline.dk/~finth/ + > Bochs/Qemu + +- UniChrome Driver + +- Init Scripts + > With an argument to init passed from the kernel? + +- #! + > Pass as argument? or pass pointer like ld-acess? + > argc/argv - Definitely + +- Network Debugging + IPv6 Autoconf + > Should IPv6 RAs be done in kernel mode, or usermode? + > Wait until something like linux's net.conf.ipv6.accept_ra is set? + > Have a custom suffix for stateless IPs? + +- Signals + > Add return value to mutexs and semaphores, and add warn_unused_ret + +- Virtual PCI bus for system configuration + > Hook in drv_pci.c, with an arch-defined array of devices + > Allow hooks on PCI config accesses (to emulate power management etc) + +- VFS Path caching + > Use a trie of path elements + > Maintain backwards cache of elements + > Support symlink caching too + +- USB Stack + > Check validity + > Rework HC API to support structure used by OHCI/ECHI + +- LVM Usablity + > /Devices/LVM/by-id/ and /Devices/LVM/by-label + +- AxWin3 + > Text editor (with a GP formatted text field?) + > Maybe a basic web browser using the surface support? + > Configuration (via lib/server) + +- Omnispeak + > Debug speed issues (tracing agian) + > Port to AxWin3 + > Trace memory corruption + +- Port dropbear! diff --git a/Usermode/Applications/Makefile.cfg b/Usermode/Applications/Makefile.cfg index e5ef7ead..0e89a7c5 100644 --- a/Usermode/Applications/Makefile.cfg +++ b/Usermode/Applications/Makefile.cfg @@ -8,7 +8,8 @@ ASFLAGS = -felf CPPFLAGS = -ffreestanding -I$(ACESSUSERDIR)/include/ -DARCHDIR_is_$(ARCHDIR) CPPFLAGS += $(addprefix -I,$(wildcard $(ACESSUSERDIR)Libraries/*/include_exp/)) CFLAGS = -fno-stack-protector $(CPPFLAGS) -LDFLAGS = -T $(OUTPUTDIR)Libs/acess.ld -rpath-link $(OUTPUTDIR)Libs -L $(OUTPUTDIR)Libs -I /Acess/Libs/ld-acess.so -lld-acess -lc $(OUTPUTDIR)Libs/crtbegin.o $(OUTPUTDIR)Libs/crtend.o `$(CC) -print-libgcc-file-name` +LDFLAGS = -T $(OUTPUTDIR)Libs/acess.ld -rpath-link $(OUTPUTDIR)Libs -L $(OUTPUTDIR)Libs -I /Acess/Libs/ld-acess.so -lld-acess -lc $(OUTPUTDIR)Libs/crtbegin.o $(OUTPUTDIR)Libs/crtend.o +LIBGCC_PATH = $(shell $(CC) -print-libgcc-file-name) # Extra-verbose errors! #CFLAGS += -Wall -Wextra -Wwrite-strings -Wshadow -Wswitch-default -Wswitch-enum -Wstrict-overflow=5 -Wfloat-equal -Wundef -Wmissing-declarations -Wlogical-op diff --git a/Usermode/Applications/Makefile.tpl b/Usermode/Applications/Makefile.tpl index 27cf9e54..c1245ae2 100644 --- a/Usermode/Applications/Makefile.tpl +++ b/Usermode/Applications/Makefile.tpl @@ -35,9 +35,9 @@ $(_BIN): $(OUTPUTDIR)Libs/acess.ld $(OUTPUTDIR)Libs/crt0.o $(_LIBS) $(OBJ) @mkdir -p $(dir $(_BIN)) @echo [LD] -o $@ ifneq ($(_DBGMAKEFILE),) - $(LD) -g $(LDFLAGS) -o $@ $(OBJ) -Map $(_OBJPREFIX)Map.txt + $(LD) -g $(LDFLAGS) -o $@ $(OBJ) -Map $(_OBJPREFIX)Map.txt $(LIBGCC_PATH) else - @$(LD) -g $(LDFLAGS) -o $@ $(OBJ) -Map $(_OBJPREFIX)Map.txt + @$(LD) -g $(LDFLAGS) -o $@ $(OBJ) -Map $(_OBJPREFIX)Map.txt $(LIBGCC_PATH) endif @$(DISASM) $(_BIN) > $(_OBJPREFIX)$(BIN).dsm diff --git a/Usermode/Applications/axwin2_src/Makefile b/Usermode/Applications/axwin2_src/Makefile deleted file mode 100644 index 89f15842..00000000 --- a/Usermode/Applications/axwin2_src/Makefile +++ /dev/null @@ -1,13 +0,0 @@ - -NAME = AxWin2 -DIRS = WM Shell_src - -SUBMAKE = $(MAKE) --no-print-directory - -all: - @$(foreach DIR,$(DIRS), echo --- $(NAME)/$(DIR) && $(SUBMAKE) -C $(DIR) $@ &&) true -install: - @$(foreach DIR,$(DIRS), echo --- $(NAME)/$(DIR) && $(SUBMAKE) -C $(DIR) $@ &&) true - -clean: - @$(foreach DIR,$(DIRS), $(SUBMAKE) -C $(DIR) $@ &&) true diff --git a/Usermode/Applications/axwin2_src/SIF.txt b/Usermode/Applications/axwin2_src/SIF.txt deleted file mode 100644 index 57c1fa7e..00000000 --- a/Usermode/Applications/axwin2_src/SIF.txt +++ /dev/null @@ -1,28 +0,0 @@ -=== Simple Image Format === - -U16 Magic 0x51F0 - This determines the endianness of the file -U16 Flags - > 0-2: Compression (0: Uncompressed, 1: RLE, 2: zlib, 3: RLE-Channel) - > 3-5: Format (0: ARGB, 1: RGB -U16 Width -U16 Height - - - -=== Compression Formats === -0 - Uncompressed - The file data is a linear sequence of Width * Height 32-bit ARGB - words (in file endianness, determined by the magic) - -1 - RLE-4 - 7-bit length followed by a 32-bit value that is repeated `n` times - (if bit 7 of the length byte is set, the next `n` 32-bit words are - verbatim) - -2 - zlib - The image data is a zlib stream of 32-bit xRGB words - -3 - RLE-Channel - The data is the alpha values, followed by red, then green, then blue - encoded as RLE with a 7-bit length and a verbatim flag (same as mode - 1, except with 8-bit values instead of 32-bit) diff --git a/Usermode/Applications/axwin2_src/Shell_src/Makefile b/Usermode/Applications/axwin2_src/Shell_src/Makefile deleted file mode 100644 index 55744b97..00000000 --- a/Usermode/Applications/axwin2_src/Shell_src/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Project: Acess GUI Default Shell - --include ../../Makefile.cfg - -CPPFLAGS += -LDFLAGS += -laxwin2 - -DIR = Apps/AxWin/1.0 -BIN = Shell -OBJ = main.o - --include ../../Makefile.tpl diff --git a/Usermode/Applications/axwin2_src/Shell_src/main.c b/Usermode/Applications/axwin2_src/Shell_src/main.c deleted file mode 100644 index f1c0416b..00000000 --- a/Usermode/Applications/axwin2_src/Shell_src/main.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Acess2 GUI Test App - * - By John Hodge (thePowersGang) - */ -#include -#include -#include - -// === CONSTANTS === -enum eTerminal_Events -{ - EVENT_NULL, - EVENT_NEW_TAB, - EVENT_CLOSE_TAB, - EVENT_EXIT -}; - -// === PROTOTYPES === - int main(int argc, char *argv[]); - int Global_HandleMessage(tAxWin_Message *Message); - int Shell_HandleMessage(tAxWin_Message *Message); - -// === GLOBALS === -tAxWin_Element *geConsole; - -// === CODE === -int main(int argc, char *argv[]) -{ - tAxWin_Element *menu, *tab; - - if(argc != 1) - { - fprintf(stderr, "Usage: %s\n", argv[0]); - fprintf(stderr, "\tThis application takes no arguments\n"); - return 0; - } - - AxWin_Register("Terminal", Global_HandleMessage); - - menu = AxWin_AddMenuItem(NULL, "File", 0); - AxWin_AddMenuItem(menu, "&New Tab\tCtrl-Shift-N", EVENT_NEW_TAB); - AxWin_AddMenuItem(menu, NULL, 0); - AxWin_AddMenuItem(menu, "&Close Tab\tCtrl-Shift-W", EVENT_CLOSE_TAB); - AxWin_AddMenuItem(menu, "E&xit\tAlt-F4", EVENT_EXIT); - - tab = AxWin_CreateWindow("root@acess: ~"); - //geConsole = AxWin_CreateElement(); - - AxWin_MessageLoop(); - - return 0; -} - -/** - */ -int Global_HandleMessage(tAxWin_Message *Message) -{ - switch(Message->ID) - { - default: - return 0; - } -} - -int Shell_HandleMessage(tAxWin_Message *Message) -{ - switch(Message->ID) - { - default: - return 0; - } -} diff --git a/Usermode/Applications/axwin2_src/WM/Makefile b/Usermode/Applications/axwin2_src/WM/Makefile deleted file mode 100644 index 19687e15..00000000 --- a/Usermode/Applications/axwin2_src/WM/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# Project: Acess GUI Window Manager - --include ../../Makefile.cfg - -CPPFLAGS += - -DIR := Apps/AxWin/1.0 -BIN := AxWinWM -OBJ := main.o helpers.o commandline.o video.o input.o video_text.o -OBJ += messages.o interface.o wm.o decorator.o render.o -OBJ += image.o - -LDFLAGS += -limage_sif -luri -lnet - --include ../../Makefile.tpl - -all: resources/LogoSmall.sif.res.h - -%.res.h: % Makefile - echo "#define RESOURCE_$(notdir $<) \\"| sed -e 's/\./_/g' > $@ - base64 $< | sed -e 's/.*/"&"\\/' >> $@ - echo "" >> $@ diff --git a/Usermode/Applications/axwin2_src/WM/commandline.c b/Usermode/Applications/axwin2_src/WM/commandline.c deleted file mode 100644 index 67db5744..00000000 --- a/Usermode/Applications/axwin2_src/WM/commandline.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#include "common.h" -#include - -// === PROTOTYPES === -void ShowUsage(char *ProgName); -void ShowHelp(char *ProgName); - -// === CODE === -void ParseCommandline(int argc, char *argv[]) -{ - int i; - char *arg; - - for( i = 1; i < argc; i++ ) - { - arg = argv[i]; - if(arg[0] == '-') - { - if( arg[1] == '-' ) - { - if( strcmp(&arg[2], "help") == 0 ) { - ShowHelp(argv[0]); - exit(EXIT_SUCCESS); - } - else { - ShowUsage(argv[0]); - exit(EXIT_FAILURE); - } - } - else - { - while( *++arg ) - { - switch(*arg) - { - case 'h': - case '?': - ShowHelp(argv[0]); - exit(EXIT_SUCCESS); - break; - default: - break; - } - } - } - } - } -} - -void ShowUsage(char *ProgName) -{ - fprintf(stderr, "Usage: %s [-h|--help]\n", ProgName); -} - -void ShowHelp(char *ProgName) -{ - ShowUsage(ProgName); - fprintf(stderr, "\n"); - fprintf(stderr, "\t--help\tShow this message\n"); -} diff --git a/Usermode/Applications/axwin2_src/WM/common.h b/Usermode/Applications/axwin2_src/WM/common.h deleted file mode 100644 index b00d6971..00000000 --- a/Usermode/Applications/axwin2_src/WM/common.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#include -#include -#include -#include // _SysDebug - -// === TYPES === -typedef struct sIPC_Type tIPC_Type; -typedef struct sFont tFont; - -struct sIPC_Type -{ - int (*GetIdentSize)(void *Ident); - int (*CompareIdent)(void *Ident1, void *Ident2); - void (*SendMessage)(void *Ident, size_t, void *Data); -}; - -#include "wm.h" -#include "image.h" -//#include "font.h" - -// === MACROS === -static inline uint32_t Video_AlphaBlend(uint32_t _orig, uint32_t _new, uint8_t _alpha) -{ - uint16_t ao,ro,go,bo; - uint16_t an,rn,gn,bn; - if( _alpha == 0 ) return _orig; - if( _alpha == 255 ) return _new; - - ao = (_orig >> 24) & 0xFF; - ro = (_orig >> 16) & 0xFF; - go = (_orig >> 8) & 0xFF; - bo = (_orig >> 0) & 0xFF; - - an = (_new >> 24) & 0xFF; - rn = (_new >> 16) & 0xFF; - gn = (_new >> 8) & 0xFF; - bn = (_new >> 0) & 0xFF; - - if( _alpha == 0x80 ) { - ao = (ao + an) / 2; - ro = (ro + rn) / 2; - go = (go + gn) / 2; - bo = (bo + bn) / 2; - } - else { - ao = ao*(255-_alpha) + an*_alpha; - ro = ro*(255-_alpha) + rn*_alpha; - go = go*(255-_alpha) + gn*_alpha; - bo = bo*(255-_alpha) + bn*_alpha; - ao /= 255*2; - ro /= 255*2; - go /= 255*2; - bo /= 255*2; - } - - return (ao << 24) | (ro << 16) | (go << 8) | bo; -} - -// === GLOBALS === -extern const char *gsTerminalDevice; -extern const char *gsMouseDevice; - -extern int giScreenWidth; -extern int giScreenHeight; -extern uint32_t *gpScreenBuffer; - -extern int giTerminalFD; -extern int giMouseFD; - -// === Functions === -extern void memset32(void *ptr, uint32_t val, size_t count); -// --- Initialisation --- -extern void ParseCommandline(int argc, char *argv[]); -// --- Messages / IPC --- -extern void IPC_Init(void); -extern void IPC_FillSelect(int *nfds, fd_set *set); -extern void IPC_HandleSelect(fd_set *set); -// --- Input --- -extern void Input_FillSelect(int *nfds, fd_set *set); -extern void Input_HandleSelect(fd_set *set); -// --- Local WM --- -extern tApplication *AxWin_RegisterClient(tIPC_Type *Method, void *Ident, const char *Name); -extern void AxWin_DeregisterClient(tApplication *App); -extern tApplication *AxWin_GetClient(tIPC_Type *Method, void *Ident); -extern tElement *AxWin_CreateAppWindow(tApplication *App, const char *Name); -// --- Video --- -extern void Video_Setup(void); -extern void Video_SetCursorPos(short X, short Y); -extern void Video_Update(void); -extern void Video_FillRect(short X, short Y, short W, short H, uint32_t Color); -extern void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color); -extern int Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text); -extern void Video_DrawImage(short X, short Y, short W, short H, tImage *Image); -// --- Interface --- -extern void Interface_Init(void); -extern void Interface_Update(void); -extern void Interface_Render(void); -// --- Decorator --- -extern void Decorator_RenderWidget(tElement *Element); - -#endif diff --git a/Usermode/Applications/axwin2_src/WM/decorator.c b/Usermode/Applications/axwin2_src/WM/decorator.c deleted file mode 100644 index 171b5261..00000000 --- a/Usermode/Applications/axwin2_src/WM/decorator.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - * - * Widget Decorator - */ -#include "common.h" -#include "wm.h" - -#define BORDER_EVERYTHING 1 - -#define BOX_BGCOLOUR 0xC0C0C0 -#define BOX_BORDER 0xA0A0A0 -#define BUTTON_BGCOLOUR 0xD0D0D0 -#define BUTTON_BORDER 0xF0F0F0 -#define TEXT_COLOUR 0x000000 - -// === CODE === -void Decorator_RenderWidget(tElement *Element) -{ - _SysDebug("Decorator_RenderWidget: (Element={Type:%i,(%i,%i) %ix%i})", - Element->Type, - Element->CachedX, Element->CachedY, - Element->CachedW, Element->CachedH - ); - - #if BORDER_EVERYTHING - Video_DrawRect(Element->CachedX, Element->CachedY, - Element->CachedW, Element->CachedH, - 0 - ); - #endif - - switch(Element->Type) - { - case ELETYPE_NONE: - case ELETYPE_BOX: break; // Box is a meta-element - - case ELETYPE_TABBAR: // Tab Bar - Video_DrawRect( - Element->CachedX, Element->CachedY, - Element->CachedW, Element->CachedH, - BOX_BORDER - ); - Video_FillRect( - Element->CachedX+1, Element->CachedY+1, - Element->CachedW-2, Element->CachedH-2, - BOX_BGCOLOUR - ); - // Enumerate Items. - break; - case ELETYPE_TOOLBAR: // Tool Bar - Video_DrawRect( - Element->CachedX, Element->CachedY, - Element->CachedW, Element->CachedH, - BOX_BORDER - ); - Video_FillRect( - Element->CachedX+1, Element->CachedY+1, - Element->CachedW-2, Element->CachedH-2, - BOX_BGCOLOUR - ); - break; - - case ELETYPE_SPACER: // Spacer (subtle line) - Video_FillRect( - Element->CachedX+3, Element->CachedY+3, - Element->CachedW-6, Element->CachedH-6, - BOX_BORDER - ); - break; - - case ELETYPE_BUTTON: // Button - Video_FillRect( - Element->CachedX+1, Element->CachedY+1, - Element->CachedW-2, Element->CachedH-2, - BUTTON_BGCOLOUR - ); - Video_DrawRect( - Element->CachedX, Element->CachedY, - Element->CachedW-1, Element->CachedH-1, - BUTTON_BORDER - ); - break; - - case ELETYPE_TEXT: - Video_DrawText( - Element->CachedX+1, Element->CachedY+1, - Element->CachedW-2, Element->CachedH-2, - NULL, - TEXT_COLOUR, - Element->Text - ); - break; - - case ELETYPE_IMAGE: - Video_DrawImage( - Element->CachedX, Element->CachedY, - Element->CachedW, Element->CachedH, - Element->Data - ); - break; - - default: - _SysDebug(" ERROR: Unknown type %i", Element->Type); - break; - } -} diff --git a/Usermode/Applications/axwin2_src/WM/font_8x16.h b/Usermode/Applications/axwin2_src/WM/font_8x16.h deleted file mode 100644 index b9bad5db..00000000 --- a/Usermode/Applications/axwin2_src/WM/font_8x16.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Taken from http://cvs.savannah.gnu.org/viewvc/vgabios/vgafonts.h?root=vgabios&view=markup - * Altered for Acess2 - */ -#define FONT_WIDTH 8 -#define FONT_HEIGHT 16 -static uint8_t VTermFont[256*16]= -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, - 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; diff --git a/Usermode/Applications/axwin2_src/WM/helpers.c b/Usermode/Applications/axwin2_src/WM/helpers.c deleted file mode 100644 index 194c0249..00000000 --- a/Usermode/Applications/axwin2_src/WM/helpers.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#include "common.h" - -// === CODE === -void memset32(void *ptr, uint32_t val, size_t count) -{ - uint32_t *dst = ptr; - while(count --) *dst++ = val; -} diff --git a/Usermode/Applications/axwin2_src/WM/image.c b/Usermode/Applications/axwin2_src/WM/image.c deleted file mode 100644 index 1d7d343d..00000000 --- a/Usermode/Applications/axwin2_src/WM/image.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - * - * Window Manager and Widget Control - */ -#include "common.h" -#include -#include -#include - -// === IMPORTS === -extern tImage *Image_SIF_Parse(void *Buffer, size_t Size); - -// === PROTOTYPES === - int UnBase64(uint8_t *Dest, char *Src, int BufSize); - -// === CODE === -/** - * \brief Open an image from a URI - */ -tImage *Image_Load(const char *URI) -{ - tURI *uri; - int filesize; - void *buf; - tImage *img; - - uri = URI_Parse(URI); - if( !uri ) { - _SysDebug("Image_Load: Unable parse as URI '%s'\n", URI); - return NULL; - } - - if( strcmp(uri->Proto, "file") == 0 ) - { - FILE *fp; - fp = fopen(uri->Path, "rb"); - if(!fp) { - _SysDebug("Image_Load: Unable to open '%s'\n", uri->Path); - free(uri); - return NULL; - } - - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - buf = malloc( filesize ); - if(!buf) { - _SysDebug("Image_Load: malloc() failed!\n"); - fclose(fp); - free(uri); - return NULL; - } - - fread(buf, filesize, 1, buf); - fclose(fp); - } - else if( strcmp(uri->Proto, "base64") == 0 ) - { - // 4 bytes of base64 = 3 bytes of binary (base 256) - filesize = strlen( uri->Path ) * 3 / 4; - buf = malloc(filesize); - if(!buf) { - _SysDebug("Image_Load: malloc() failed!\n"); - free(uri); - return NULL; - } - - filesize = UnBase64(buf, uri->Path, filesize); - } - else - { - _SysDebug("Image_Load: Unknow protocol '%s'\n", uri->Proto); - free(uri); - return NULL; - } - - img = Image_SIF_Parse(buf, filesize); - free(buf); - free(uri); - if( !img ) { - _SysDebug("Image_Load: Unable to parse SIF from '%s'\n", URI); - return NULL; - } - - return img; -} - -/** - * \brief Decode a Base64 value - */ -int UnBase64(uint8_t *Dest, char *Src, int BufSize) -{ - uint32_t val; - int i, j; - char *start_src = Src; - - for( i = 0; i+2 < BufSize; i += 3 ) - { - val = 0; - for( j = 0; j < 4; j++, Src ++ ) { - if('A' <= *Src && *Src <= 'Z') - val |= (*Src - 'A') << ((3-j)*6); - else if('a' <= *Src && *Src <= 'z') - val |= (*Src - 'a' + 26) << ((3-j)*6); - else if('0' <= *Src && *Src <= '9') - val |= (*Src - '0' + 52) << ((3-j)*6); - else if(*Src == '+') - val |= 62 << ((3-j)*6); - else if(*Src == '/') - val |= 63 << ((3-j)*6); - else if(!*Src) - break; - else if(*Src != '=') - j --; // Ignore invalid characters - } - Dest[i ] = (val >> 16) & 0xFF; - Dest[i+1] = (val >> 8) & 0xFF; - Dest[i+2] = val & 0xFF; - if(j != 4) break; - } - - // Finish things off - if(i < BufSize) - Dest[i] = (val >> 16) & 0xFF; - if(i+1 < BufSize) - Dest[i+1] = (val >> 8) & 0xFF; - - return Src - start_src; -} diff --git a/Usermode/Applications/axwin2_src/WM/image.h b/Usermode/Applications/axwin2_src/WM/image.h deleted file mode 100644 index 6cda85b4..00000000 --- a/Usermode/Applications/axwin2_src/WM/image.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#ifndef _IMAGE_H_ -#define _IMAGE_H_ - -typedef struct sImage tImage; - -struct sImage -{ - short Width; - short Height; - int Format; - uint8_t Data[]; -}; - -enum eImageFormats -{ - IMGFMT_BGRA, - IMGFMT_RGB, - NUM_IMGFMTS -}; - -// === PROTOTYPES === -extern tImage *Image_Load(const char *URI); - -#endif diff --git a/Usermode/Applications/axwin2_src/WM/input.c b/Usermode/Applications/axwin2_src/WM/input.c deleted file mode 100644 index 93869328..00000000 --- a/Usermode/Applications/axwin2_src/WM/input.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#include "common.h" -#include - -#define JOY_IOCTL_GETSETAXISLIMIT 6 -#define JOY_IOCTL_GETSETAXISPOSITION 7 - -// === CODE === -int Input_Init(void) -{ - struct { - int Num, Value; - } num_value; - - // Open mouse for RW - giMouseFD = open(gsMouseDevice, 3); - - // Set mouse limits - num_value.Num = 0; - num_value.Value = giScreenWidth; - ioctl(giMouseFD, JOY_IOCTL_GETSETAXISLIMIT, &num_value); - num_value.Value = giScreenWidth/2; - ioctl(giMouseFD, JOY_IOCTL_GETSETAXISPOSITION, &num_value); - - num_value.Num = 1; - num_value.Value = giScreenHeight; - ioctl(giMouseFD, JOY_IOCTL_GETSETAXISLIMIT, &num_value); - num_value.Value = giScreenHeight/2; - ioctl(giMouseFD, JOY_IOCTL_GETSETAXISPOSITION, &num_value); - - return 0; -} - -void Input_FillSelect(int *nfds, fd_set *set) -{ - if(*nfds < giTerminalFD) *nfds = giTerminalFD; - if(*nfds < giMouseFD) *nfds = giMouseFD; - FD_SET(giTerminalFD, set); - FD_SET(giMouseFD, set); -} - -void Input_HandleSelect(fd_set *set) -{ - if(FD_ISSET(giTerminalFD, set)) - { - uint32_t codepoint; - if( read(giTerminalFD, &codepoint, sizeof(codepoint)) != sizeof(codepoint) ) - { - // oops, error - } - // TODO: pass on to message handler - _SysDebug("Keypress 0x%x", codepoint); - } - - if(FD_ISSET(giMouseFD, set)) - { - struct sMouseInfo { - uint16_t NAxies; - uint16_t NButtons; - struct sMouseAxis { - int16_t MinValue; - int16_t MaxValue; - int16_t CurValue; - uint16_t CursorPos; - } Axies[2]; - uint8_t Buttons[3]; - } mouseinfo; - - seek(giMouseFD, 0, SEEK_SET); - if( read(giMouseFD, &mouseinfo, sizeof(mouseinfo)) != sizeof(mouseinfo) ) - { - // Not a 3 button mouse, oops - return ; - } - -// _SysDebug("sizeof(uint16_t) = %i, sizeof(int16_t) = %i", -// sizeof(uint16_t), sizeof(int16_t)); -// _SysDebug("NAxies=%i,NButtons=%i", mouseinfo.NAxies, mouseinfo.NButtons); -// _SysDebug("offsetof(Axies[0].MinValue) = %i", offsetof(struct sMouseInfo, Axies[0].MinValue)); -// _SysDebug("[0] = {MinValue=%i,MaxValue=%i,CurValue=%i}", -// mouseinfo.Axies[0].MinValue, mouseinfo.Axies[0].MaxValue, -// mouseinfo.Axies[0].CurValue -// ); - // Handle movement - Video_SetCursorPos( mouseinfo.Axies[0].CursorPos, mouseinfo.Axies[1].CursorPos ); -// _SysDebug("Cursor to %i,%i", mouseinfo.Axies[0].CursorPos, mouseinfo.Axies[1].CursorPos); - } -} diff --git a/Usermode/Applications/axwin2_src/WM/interface.c b/Usermode/Applications/axwin2_src/WM/interface.c deleted file mode 100644 index 91396ee6..00000000 --- a/Usermode/Applications/axwin2_src/WM/interface.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - * - * interface.c - * > Main Overarching UI - */ -#include "common.h" -#include "resources/LogoSmall.sif.res.h" - -// === GLOBALS == - int giInterface_Width = 0; - int giInterface_HeaderBarSize = 20; - int giInterface_TabBarSize = 20; -tElement *gpInterface_Sidebar; -tElement *gpInterface_ProgramList; -tElement *gpInterface_MainArea; -tElement *gpInterface_HeaderBar; -tElement *gpInterface_TabBar; -tElement *gpInterface_TabContent; -const char csLogoSmall[] = "base64:///"RESOURCE_LogoSmall_sif; -tApplication *gpInterface_CurrentApp; - -typedef struct sApplicationLink tApplicationLink; - -struct sApplicationLink { - tApplication *App; - tElement *Button; - char Name[]; -}; - -// === CODE === -/** - * \brief Initialise the UI - */ -void Interface_Init(void) -{ - tElement *btn, *text; - tElement *ele; - - // Calculate sizes - giInterface_Width = giScreenWidth/16; - - // Set root window to no-border - AxWin_SetFlags(NULL, 0); - - // -- Create Sidebar (Menu and Window List) -- - gpInterface_Sidebar = AxWin_CreateElement(NULL, ELETYPE_TOOLBAR, ELEFLAG_VERTICAL, "Sidebar"); - AxWin_SetSize( gpInterface_Sidebar, giInterface_Width ); - - // > System Menu Button - btn = AxWin_CreateElement(gpInterface_Sidebar, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH, "SystemMenu"); - AxWin_SetSize(btn, giInterface_Width-4); - //text = AxWin_CreateElement(btn, ELETYPE_IMAGE, ELEFLAG_SCALE, "MenuLogo"); - text = AxWin_CreateElement(btn, ELETYPE_IMAGE, 0, "MenuLogo"); - //AxWin_SetText(text, "file:///LogoSmall.sif"); - AxWin_SetText(text, csLogoSmall); - - // > Plain
style spacer - ele = AxWin_CreateElement(gpInterface_Sidebar, ELETYPE_SPACER, ELEFLAG_NOSTRETCH, "SideBar Spacer Top"); - AxWin_SetSize(ele, 4); - - // > Application List (Window list on most OSs) - gpInterface_ProgramList = AxWin_CreateElement(gpInterface_Sidebar, ELETYPE_BOX, ELEFLAG_VERTICAL, "ProgramList"); - - // > Plain
style spacer - ele = AxWin_CreateElement(gpInterface_Sidebar, ELETYPE_SPACER, ELEFLAG_NOSTRETCH, "SideBar Spacer Bottom"); - AxWin_SetSize(ele, 4); - - // > Version/Time - text = AxWin_CreateElement(gpInterface_Sidebar, ELETYPE_TEXT, ELEFLAG_NOSTRETCH, "Version String"); - AxWin_SetSize(text, 20); - AxWin_SetText(text, "2.0"); - - // -- - // -- Create Main Area and regions within -- - // -- - // > Righthand Area - gpInterface_MainArea = AxWin_CreateElement(NULL, ELETYPE_BOX, ELEFLAG_VERTICAL, "MainArea"); - // > Header Bar (Title) - gpInterface_HeaderBar = AxWin_CreateElement(gpInterface_MainArea, ELETYPE_BOX, 0, "HeaderBar"); - AxWin_SetSize(gpInterface_HeaderBar, giInterface_HeaderBarSize); - text = AxWin_CreateElement(gpInterface_HeaderBar, ELETYPE_TEXT, 0, NULL); - AxWin_SetText(text, "Acess2 GUI - By thePowersGang (John Hodge)"); - // > Tab Bar (Current windows) - gpInterface_TabBar = AxWin_CreateElement(gpInterface_MainArea, ELETYPE_TABBAR, 0, "TabBar"); - AxWin_SetSize(gpInterface_TabBar, giInterface_TabBarSize); - // > Application Space - gpInterface_TabContent = AxWin_CreateElement(gpInterface_MainArea, ELETYPE_BOX, 0, "TabContent"); -} - -void Interface_Update(void) -{ -// tApplication *app; -// tApplicationLink *lnk; - giInterface_Width = giScreenWidth/16; - AxWin_SetSize( gpInterface_Sidebar, giInterface_Width ); - - // Scan application list for changes - // - HACK for now, just directly access it -// for( app = gWM_Applications; app; app = app->Next ) -// { -// AxWin_CreateElement(); -// } - - // Update current tab list -} - -void Interface_Render(void) -{ - Video_FillRect( - 0, 0, - giInterface_Width, giScreenHeight, - 0xDDDDDD); - - Video_Update(); -} diff --git a/Usermode/Applications/axwin2_src/WM/main.c b/Usermode/Applications/axwin2_src/WM/main.c deleted file mode 100644 index 48e47ff7..00000000 --- a/Usermode/Applications/axwin2_src/WM/main.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#include "common.h" -#include - -// === IMPORTS === -extern void WM_Update(void); -extern int Input_Init(void); - -// === GLOBALS === -const char *gsTerminalDevice = NULL; -const char *gsMouseDevice = NULL; - - int giScreenWidth = 640; - int giScreenHeight = 480; -uint32_t *gpScreenBuffer = NULL; - - int giTerminalFD = -1; - int giMouseFD = -1; - - -// === CODE === -/** - * \brief Program Entrypoint - */ -int main(int argc, char *argv[]) -{ - ParseCommandline(argc, argv); - - if( gsTerminalDevice == NULL ) { - gsTerminalDevice = "/Devices/VTerm/6"; - } - if( gsMouseDevice == NULL ) { - gsMouseDevice = "/Devices/PS2Mouse"; - } - - Video_Setup(); - Interface_Init(); - IPC_Init(); - Input_Init(); - - WM_Update(); - - // Main Loop - for(;;) - { - fd_set fds; - int nfds = 0; - FD_ZERO(&fds); - - Input_FillSelect(&nfds, &fds); - IPC_FillSelect(&nfds, &fds); - - nfds ++; - select(nfds, &fds, NULL, NULL, NULL); - - Input_HandleSelect(&fds); - IPC_HandleSelect(&fds); - } - return 0; -} - diff --git a/Usermode/Applications/axwin2_src/WM/messages.c b/Usermode/Applications/axwin2_src/WM/messages.c deleted file mode 100644 index f25e1c4b..00000000 --- a/Usermode/Applications/axwin2_src/WM/messages.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#include "common.h" -#include -#include -#include -#include - -#define AXWIN_PORT 4101 - -#define STATICBUF_SIZE 64 - -// === TYPES === - -// === PROTOTYPES === -void IPC_Init(void); -void IPC_FillSelect(int *nfds, fd_set *set); -void IPC_HandleSelect(fd_set *set); -void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg); -void IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value); - int IPC_Type_Datagram_GetSize(void *Ident); - int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2); -void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data); - int IPC_Type_Sys_GetSize(void *Ident); - int IPC_Type_Sys_Compare(void *Ident1, void *Ident2); -void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data); - -// === GLOBALS === - int giNetworkFileHandle = -1; - int giMessagesFileHandle = -1; -tIPC_Type gIPC_Type_Datagram = { - IPC_Type_Datagram_GetSize, - IPC_Type_Datagram_Compare, - IPC_Type_Datagram_Send -}; -tIPC_Type gIPC_Type_SysMessage = { - IPC_Type_Sys_GetSize, - IPC_Type_Sys_Compare, - IPC_Type_Sys_Send -}; - -// === CODE === -void IPC_Init(void) -{ - int tmp; - // TODO: Check this - giNetworkFileHandle = open("/Devices/ip/loop/udp", OPENFLAG_READ); - tmp = AXWIN_PORT; ioctl(giNetworkFileHandle, 4, &tmp); // TODO: Don't hard-code IOCtl number -} - -void IPC_FillSelect(int *nfds, fd_set *set) -{ - if( giNetworkFileHandle > *nfds ) *nfds = giNetworkFileHandle; - FD_SET(giNetworkFileHandle, set); -} - -void IPC_HandleSelect(fd_set *set) -{ - if( FD_ISSET(giNetworkFileHandle, set) ) - { - char staticBuf[STATICBUF_SIZE]; - int readlen, identlen; - char *msg; - - readlen = read(giNetworkFileHandle, staticBuf, sizeof(staticBuf)); - - identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] ); - msg = staticBuf + identlen; - - IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg); - _SysDebug("IPC_HandleSelect: UDP handled"); - } - - while(SysGetMessage(NULL, NULL)) - { - pid_t tid; - int len = SysGetMessage(&tid, NULL); - char data[len]; - SysGetMessage(NULL, data); - - IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data); - _SysDebug("IPC_HandleSelect: Message handled"); - } -} - -void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg) -{ - tApplication *app; - tElement *ele; - - _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)", - IPCType, Ident, MsgLen, Msg); - - if( MsgLen < sizeof(tAxWin_Message) ) - return ; - if( MsgLen < sizeof(tAxWin_Message) + Msg->Size ) - return ; - - app = AxWin_GetClient(IPCType, Ident); - - switch((enum eAxWin_Messages) Msg->ID) - { - // --- Ping message (reset timeout and get server version) - case MSG_SREQ_PING: - _SysDebug(" IPC_Handle: MSG_SREQ_PING"); - if( MsgLen < sizeof(tAxWin_Message) + 4 ) return; - Msg->ID = MSG_SRSP_VERSION; - Msg->Size = 4; - Msg->Data[0] = 0; - Msg->Data[1] = 1; - *(uint16_t*)&Msg->Data[2] = -1; - IPCType->SendMessage(Ident, sizeof(Msg->ID), Msg); - break; - - - // --- Register an application - case MSG_SREQ_REGISTER: - _SysDebug(" IPC_Handle: MSG_SREQ_REGISTER"); - if( Msg->Data[Msg->Size-1] != '\0' ) { - // Invalid message - _SysDebug("IPC_Handle: RETURN - Not NULL terminated"); - return ; - } - - if( app != NULL ) { - _SysDebug("Notice: Duplicate registration (%s)\n", Msg->Data); - return ; - } - - // TODO: Should this function be implemented here? - AxWin_RegisterClient(IPCType, Ident, Msg->Data); - break; - - // --- Create a window - case MSG_SREQ_ADDWIN: - _SysDebug(" IPC_Handle: MSG_SREQ_ADDWIN"); - if( Msg->Data[Msg->Size-1] != '\0' ) { - // Invalid message - return ; - } - - ele = AxWin_CreateAppWindow(app, Msg->Data); - IPC_ReturnValue(IPCType, Ident, MSG_SREQ_ADDWIN, ele->ApplicationID); - break; - - // --- Set a window's icon - case MSG_SREQ_SETICON: - _SysDebug(" IPC_Handle: MSG_SREQ_SETICON"); - // TODO: Find a good way of implementing this - break; - - // --- Create an element - case MSG_SREQ_INSERT: { - _SysDebug(" IPC_Handle: MSG_SREQ_INSERT"); - struct sAxWin_SReq_NewElement *info = (void *)Msg->Data; - - if( Msg->Size != sizeof(*info) ) return; - - if( !app || info->Parent > app->MaxElementIndex ) return ; - - ele = AxWin_CreateElement( app->EleIndex[info->Parent], info->Type, info->Flags, NULL ); - IPC_ReturnValue(IPCType, Ident, MSG_SREQ_ADDWIN, ele->ApplicationID); - break; } - - // --- Unknown message - default: - fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType); - _SysDebug("WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType); - break; - } -} - -void IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value) -{ - char data[sizeof(tAxWin_Message) + sizeof(tAxWin_RetMsg)]; - tAxWin_Message *msg = (void *)data; - tAxWin_RetMsg *ret_msg = (void *)msg->Data; - - msg->Source = 0; // 0 = Server - msg->ID = MSG_SRSP_RETURN; - msg->Size = sizeof(tAxWin_RetMsg); - ret_msg->ReqID = MessageID; - ret_msg->Rsvd = 0; - ret_msg->Value = Value; - - IPCType->SendMessage(Ident, sizeof(data), data); -} - -int IPC_Type_Datagram_GetSize(void *Ident) -{ - return 4 + Net_GetAddressSize( ((uint16_t*)Ident)[1] ); -} - -int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2) -{ - // Pass the buck :) - // - No need to worry about mis-matching sizes, as the size is computed - // from the 3rd/4th bytes, hence it will differ before the size is hit. - return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1)); -} - -void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data) -{ - int identlen = IPC_Type_Datagram_GetSize(Ident); - char tmpbuf[ identlen + Length ]; - memcpy(tmpbuf, Ident, identlen); // Header - memcpy(tmpbuf + identlen, Data, Length); // Data - // TODO: Handle fragmented packets - write(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf)); -} - -int IPC_Type_Sys_GetSize(void *Ident) -{ - return sizeof(pid_t); -} - -int IPC_Type_Sys_Compare(void *Ident1, void *Ident2) -{ - return *(int*)Ident1 - *(int*)Ident2; -} - -void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data) -{ - SysSendMessage( *(tid_t*)Ident, Length, Data ); -} diff --git a/Usermode/Applications/axwin2_src/WM/render.c b/Usermode/Applications/axwin2_src/WM/render.c deleted file mode 100644 index 0ee9e80d..00000000 --- a/Usermode/Applications/axwin2_src/WM/render.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - * - * Rendering code - */ -#include "common.h" -#include -#include -#include "wm.h" -#include // _SysDebug - -// === IMPORTS === -extern void Decorator_RenderWidget(tElement *Element); -extern tElement gWM_RootElement; -extern tApplication *gWM_Applications; -extern int giWM_MaxAreaX; -extern int giWM_MaxAreaY; -extern int giWM_MaxAreaW; -extern int giWM_MaxAreaH; - -// === PROTOTYPES === -void WM_UpdateMinDims(tElement *Element); -void WM_UpdateDimensions(tElement *Element, int Pass); -void WM_UpdatePosition(tElement *Element); -void WM_RenderWidget(tElement *Element); -void WM_Update(void); - -// === CODE === -/** - * \brief Updates the dimensions of an element - * \todo What is the \a Pass parameter for - * - * The dimensions of an element are calculated from the parent's - * cross dimension (the side at right angles to the alignment) sans some - * padding. - */ -void WM_UpdateDimensions(tElement *Element, int Pass) -{ - tElement *child; - int nChildren = 0; - int nFixed = 0; - int maxCross = 0; - int fixedSize = 0; - int fullCross, dynWith; - - _SysDebug("WM_UpdateDimensions %p'%s'", Element, Element->DebugName); - _SysDebug(" -> Flags = 0x%x", Element->Flags); - _SysDebug(" ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i", - Element->CachedH, Element->PaddingT, Element->PaddingB - ); - _SysDebug(" ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i", - Element->CachedW, Element->PaddingL, Element->PaddingR - ); - - // Pass 1 - for( child = Element->FirstChild; child; child = child->NextSibling ) - { - if( child->Flags & ELEFLAG_ABSOLUTEPOS ) - continue ; - - _SysDebug(" > %p'%s' ->FixedWith = %i", child, child->DebugName, child->FixedWith); - if( child->FixedWith ) - { - nFixed ++; - fixedSize += child->FixedWith; - } - - if( child->FixedCross && maxCross < child->FixedCross ) - maxCross = child->FixedCross; - if( child->MinCross && maxCross < child->MinCross ) - maxCross = child->MinCross; - nChildren ++; - } - - _SysDebug(" - nChildren = %i, nFixed = %i", Element, nChildren, nFixed); - if( nChildren > nFixed ) { - if( Element->Flags & ELEFLAG_VERTICAL ) - dynWith = Element->CachedH - Element->PaddingT - - Element->PaddingB; - else - dynWith = Element->CachedW - Element->PaddingL - - Element->PaddingR; - dynWith -= fixedSize; - if( dynWith < 0 ) return ; - dynWith /= nChildren - nFixed; - _SysDebug(" - dynWith = %i", dynWith); - } - - if( Element->Flags & ELEFLAG_VERTICAL ) - fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR; - else - fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB; - - _SysDebug(" - fullCross = %i", Element, fullCross); - - // Pass 2 - Set sizes and recurse - for( child = Element->FirstChild; child; child = child->NextSibling ) - { - int cross, with; - - _SysDebug(" > %p'%s' ->MinCross = %i", child, child->DebugName, child->MinCross); - - - // --- Cross Size --- - if( child->FixedCross ) - cross = child->FixedCross; - // Expand to fill? - // TODO: Extra flag so options are (Expand, Equal, Wrap) - else if( child->Flags & ELEFLAG_NOEXPAND ) - cross = child->MinCross; - else - cross = fullCross; - _SysDebug(" > %p'%s' - cross = %i", child, child->DebugName, cross); - if( Element->Flags & ELEFLAG_VERTICAL ) - child->CachedW = cross; - else - child->CachedH = cross; - - // --- With Size --- - if( child->FixedWith) - with = child->FixedWith; - else if( child->Flags & ELEFLAG_NOSTRETCH ) - with = child->MinWith; - else - with = dynWith; - _SysDebug(" > %p'%s' - with = %i", child, child->DebugName, with); - if( Element->Flags & ELEFLAG_VERTICAL ) - child->CachedH = with; - else - child->CachedW = with; - - WM_UpdateDimensions(child, Pass); - } - - _SysDebug("%p'%s' Done", Element, Element->DebugName); -} - -/** - * \brief Updates the position of an element - * - * The parent element sets the positions of its children - */ -void WM_UpdatePosition(tElement *Element) -{ - tElement *child; - int x, y; - static int depth = 0; - char indent[depth+1]; - - if( Element->Flags & ELEFLAG_NORENDER ) return ; - - memset(indent, ' ', depth); - indent[depth] = '\0'; - depth ++; - - _SysDebug("%sWM_UpdatePosition %p'%s'{PaddingL:%i, PaddingT:%i}", - indent, Element, Element->DebugName, Element->PaddingL, Element->PaddingT); - - // Initialise - x = Element->CachedX + Element->PaddingL; - y = Element->CachedY + Element->PaddingT; - - _SysDebug("%s- Alignment = %s", indent, - (Element->Flags & ELEFLAG_VERTICAL) ? "vertical" : "horizontal"); - - // Update each child - for(child = Element->FirstChild; child; child = child->NextSibling) - { - _SysDebug("%s- x = %i, y = %i", indent, x, y); - child->CachedX = x; - child->CachedY = y; - - // Set Alignment - if( Element->Flags & ELEFLAG_ALIGN_CENTER ) { - _SysDebug("%sChild being aligned to center", indent); - if(Element->Flags & ELEFLAG_VERTICAL) - child->CachedX += Element->CachedW/2 - child->CachedW/2; - else - child->CachedY += Element->CachedH/2 - child->CachedH/2; - } - else if( Element->Flags & ELEFLAG_ALIGN_END) { - _SysDebug("%sChild being aligned to end", indent); - if(Element->Flags & ELEFLAG_VERTICAL ) - child->CachedX += Element->CachedW - - Element->PaddingL - Element->PaddingR - - child->CachedW; - else - child->CachedY += Element->CachedH - - Element->PaddingT - - Element->PaddingB - - child->CachedH; - } - - _SysDebug("%s> %p'%s' at (%i,%i)", indent, child, child->DebugName, - child->CachedX, child->CachedY); - - // Update child's children positions - WM_UpdatePosition(child); - - // Increment - if(Element->Flags & ELEFLAG_VERTICAL ) { - y += child->CachedH + Element->GapSize; - } - else { - x += child->CachedW + Element->GapSize; - } - } - - _SysDebug("%sElement %p'%s' (%i,%i)", - indent, Element, Element->DebugName, Element->CachedX, Element->CachedY - ); - depth --; -} - -/** - * \brief Update the minimum dimensions of the element - * \note Called after a child's minimum dimensions have changed - */ -void WM_UpdateMinDims(tElement *Element) -{ - tElement *child; - - if(!Element) return; - - Element->MinCross = 0; - Element->MinWith = 0; - - for(child = Element->FirstChild; child; child = child->NextSibling) - { - if( Element->Parent && - (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL) - ) - { - if(child->FixedCross) - Element->MinCross += child->FixedCross; - else - Element->MinCross += child->MinCross; - if(child->FixedWith) - Element->MinWith += child->FixedWith; - else - Element->MinWith += child->MinWith; - } - else - { - if(child->FixedCross) - Element->MinWith += child->FixedCross; - else - Element->MinWith += child->MinCross; - if(child->FixedWith) - Element->MinCross += child->FixedWith; - else - Element->MinCross += child->MinWith; - } - } - - // Recurse upwards - WM_UpdateMinDims(Element->Parent); -} - -// --- Render --- -void WM_RenderWidget(tElement *Element) -{ - tElement *child; - - if( Element->Flags & ELEFLAG_NORENDER ) return ; - if( Element->Flags & ELEFLAG_INVISIBLE ) return ; - - Decorator_RenderWidget(Element); - - for(child = Element->FirstChild; child; child = child->NextSibling) - { - WM_RenderWidget(child); - } -} - -void WM_UpdateWindow(tElement *Ele) -{ - WM_UpdateDimensions( Ele, 0 ); - WM_UpdatePosition( Ele ); - WM_RenderWidget( Ele ); -} - -void WM_Update(void) -{ - tApplication *app; - tElement *ele; - - for( app = gWM_Applications; app; app = app->Next ) - { - for( ele = app->MetaElement.FirstChild; ele; ele = ele->NextSibling ) { - if( ele->Flags & ELEFLAG_WINDOW_MAXIMISED ) { - ele->CachedX = giWM_MaxAreaX; - ele->CachedY = giWM_MaxAreaY; - ele->CachedW = giWM_MaxAreaW; - ele->CachedH = giWM_MaxAreaH; - } - ele->Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE; - WM_UpdateWindow(ele); - } - } - - gWM_RootElement.CachedX = 0; - gWM_RootElement.CachedY = 0; - gWM_RootElement.CachedW = giScreenWidth; - gWM_RootElement.CachedH = giScreenHeight; - gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE; - - WM_UpdateWindow( &gWM_RootElement ); - - Video_Update(); -} diff --git a/Usermode/Applications/axwin2_src/WM/resources/LogoSmall.sif b/Usermode/Applications/axwin2_src/WM/resources/LogoSmall.sif deleted file mode 100644 index 2064e489..00000000 Binary files a/Usermode/Applications/axwin2_src/WM/resources/LogoSmall.sif and /dev/null differ diff --git a/Usermode/Applications/axwin2_src/WM/resources/cursor.h b/Usermode/Applications/axwin2_src/WM/resources/cursor.h deleted file mode 100644 index 3cce1f25..00000000 --- a/Usermode/Applications/axwin2_src/WM/resources/cursor.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - */ -#ifndef _RESORUCE_CURSOR_H -#define _RESORUCE_CURSOR_H - -#include - -static struct { - uint16_t W, H, OfsX, OfsY; - uint32_t Data[]; -} cCursorBitmap = { - 8, 16, 0, 0, - { - 0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFF000000, 0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFF000000, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, 0x00000000, - 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, - 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, - 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0xFF000000, 0xFF000000, - 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, - 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, - 0xFF000000, 0x00000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFF000000, 0xFF000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 - } -}; - -#endif - diff --git a/Usermode/Applications/axwin2_src/WM/video.c b/Usermode/Applications/axwin2_src/WM/video.c deleted file mode 100644 index 4121fbeb..00000000 --- a/Usermode/Applications/axwin2_src/WM/video.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#include "common.h" -#include -#include -#include -#include "resources/cursor.h" - -// === PROTOTYPES === -void Video_Setup(void); -void Video_SetCursorPos(short X, short Y); -void Video_Update(void); -void Video_FillRect(short X, short Y, short W, short H, uint32_t Color); -void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color); - -// === GLOBALS === - int giVideo_CursorX; - int giVideo_CursorY; - -// === CODE === -void Video_Setup(void) -{ - int tmpInt; - - // Open terminal - giTerminalFD = open(gsTerminalDevice, OPENFLAG_READ|OPENFLAG_WRITE); - if( giTerminalFD == -1 ) - { - fprintf(stderr, "ERROR: Unable to open '%s' (%i)\n", gsTerminalDevice, _errno); - exit(-1); - } - - // Set width - tmpInt = giScreenWidth; - tmpInt = ioctl( giTerminalFD, TERM_IOCTL_WIDTH, &tmpInt ); - if(tmpInt != giScreenWidth) - { - fprintf(stderr, "Warning: Selected width (%i) is invalid, clipped to %i\n", - giScreenWidth, tmpInt); - giScreenWidth = tmpInt; - } - - // Set height - tmpInt = giScreenHeight; - tmpInt = ioctl( giTerminalFD, TERM_IOCTL_HEIGHT, &tmpInt ); - if(tmpInt != giScreenHeight) - { - fprintf(stderr, "Warning: Selected height (%i) is invalid, clipped to %i\n", - giScreenHeight, tmpInt); - giScreenHeight = tmpInt; - } - - // Set mode to video - tmpInt = TERM_MODE_FB; - ioctl( giTerminalFD, TERM_IOCTL_MODETYPE, &tmpInt ); - - // Force VT to be shown - ioctl( giTerminalFD, TERM_IOCTL_FORCESHOW, NULL ); - - // Create local framebuffer (back buffer) - gpScreenBuffer = malloc( giScreenWidth*giScreenHeight*4 ); - memset32( gpScreenBuffer, 0x8888FF, giScreenWidth*giScreenHeight ); - - // Set cursor position and bitmap - ioctl(giTerminalFD, TERM_IOCTL_SETCURSORBITMAP, &cCursorBitmap); - Video_SetCursorPos( giScreenWidth/2, giScreenHeight/2 ); - - Video_Update(); -} - -void Video_Update(void) -{ - //seek(giTerminalFD, 0, SEEK_SET); - seek(giTerminalFD, 0, 1); - write(giTerminalFD, gpScreenBuffer, giScreenWidth*giScreenHeight*4); -} - -void Video_SetCursorPos(short X, short Y) -{ - struct { - uint16_t x; - uint16_t y; - } pos; - pos.x = giVideo_CursorX = X; - pos.y = giVideo_CursorY = Y; - ioctl(giTerminalFD, TERM_IOCTL_GETSETCURSOR, &pos); -} - -void Video_FillRect(short X, short Y, short W, short H, uint32_t Color) -{ - uint32_t *buf = gpScreenBuffer + Y*giScreenWidth + X; - - _SysDebug("Video_FillRect: (X=%i, Y=%i, W=%i, H=%i, Color=%08x)", - X, Y, W, H, Color); - - if(W < 0 || X < 0 || X >= giScreenWidth) return ; - if(X + W > giScreenWidth) W = giScreenWidth - X; - - if(H < 0 || Y < 0 || Y >= giScreenHeight) return ; - if(Y + H > giScreenHeight) H = giScreenHeight - Y; - - while( H -- ) - { - memset32( buf, Color, W ); - buf += giScreenWidth; - } -} - -void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color) -{ - Video_FillRect(X, Y, W, 1, Color); - Video_FillRect(X, Y+H-1, W, 1, Color); - Video_FillRect(X, Y, 1, H, Color); - Video_FillRect(X+W-1, Y, 1, H, Color); -} - -/** - * \brief Draw an image to the screen - * \todo Maybe have support for an offset in the image - */ -void Video_DrawImage(short X, short Y, short W, short H, tImage *Image) -{ - int x, y; - uint8_t *buf = (uint8_t *)(gpScreenBuffer + Y*giScreenWidth + X); - uint8_t *data; - - // Sanity please - if( !Image ) - return ; - - // Bounds Check - if( X >= giScreenWidth ) return ; - if( Y >= giScreenHeight ) return ; - - // Wrap to image size - if( W > Image->Width ) W = Image->Width; - if( H > Image->Height ) H = Image->Height; - - // Wrap to screen size - if( X + W > giScreenWidth ) W = giScreenWidth - X; - if( Y + H > giScreenHeight ) H = giScreenHeight - Y; - - // Do the render - data = Image->Data; - switch( Image->Format ) - { - case IMGFMT_BGRA: - for( y = 0; y < H; y ++ ) - { - int r, g, b, a; // New - int or, og, ob; // Original - for( x = 0; x < W; x ++ ) - { - b = data[x*4+0]; g = data[x*4+1]; r = data[x*4+2]; a = data[x*4+3]; - if( a == 0 ) continue; // 100% transparent - ob = buf[x*4+0]; og = buf[x*4+1]; or = buf[x*4+2]; - // Handle Alpha - switch(a) - { - // Transparent: Handled above - // Solid - case 0xFF: break; - // Half - case 0x80: - r = (or + r) / 2; - g = (og + g) / 2; - b = (ob + b) / 2; - break; - // General - default: - r = (or * (255-a) + r * a) / 255; - g = (og * (255-a) + g * a) / 255; - b = (ob * (255-a) + b * a) / 255; - break; - } - buf[x*4+0] = b; buf[x*4+1] = g; buf[x*4+2] = r; - } - data += Image->Width * 4; - buf += giScreenWidth * 4; - } - break; - - // RGB - case IMGFMT_RGB: - for( y = 0; y < H; y ++ ) - { - for( x = 0; x < W; x ++ ) - { - buf[x*4+0] = data[x*3+2]; // Blue - buf[x*4+1] = data[x*3+1]; // Green - buf[x*4+2] = data[x*3+0]; // Red - } - data += W * 3; - buf += giScreenWidth * 4; - } - break; - default: - _SysDebug("ERROR: Unknown image format %i\n", Image->Format); - break; - } -} diff --git a/Usermode/Applications/axwin2_src/WM/video_text.c b/Usermode/Applications/axwin2_src/WM/video_text.c deleted file mode 100644 index 3d680d5d..00000000 --- a/Usermode/Applications/axwin2_src/WM/video_text.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - */ -#include -#include "common.h" - -typedef struct sGlyph { - struct sGlyph *Next; - struct sGlyph *Prev; - - uint32_t Codepoint; - - // Effective dimensions (distance to move 'cursor') - short Width; - short Height; - - // Distance from the current cursor position to render at - short OffsetX; - short OffsetY; - - // True dimensions (size of the bitmap - short TrueWidth; - short TrueHeight; - - // Bitmap Data - uint8_t Bitmap[]; // 8-bit alpha - -} tGlyph; - -struct sFont { - struct sFont *Next; - int ReferenceCount; - - tGlyph *AsciiGlyphs[128]; // Glyphs 0-127 - - tGlyph *FirstGlyph; - tGlyph *LastGlyph; - - tGlyph *(*CacheGlyph)(struct sFont *this, uint32_t Codepoint); - -}; - - -// === PROTOTYPES === - int Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text); -void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H); -tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint); -void _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color); -tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint); - int ReadUTF8(const char *Input, uint32_t *Output); - -// === GLOBALS === -tFont gSystemFont = { - .CacheGlyph = _SystemFont_CacheGlyph -}; - -// === CODE === -/** - * \brief Draw text to the screen - */ -int Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text) -{ - int xOfs = 0; - tGlyph *glyph; - uint32_t ch = 0; - - _SysDebug("Video_DrawText: (X=%i,Y=%i,W=%i,H=%i,Font=%p,", X, Y, W, H, Font); - _SysDebug(" Color=%08x,Text='%s')", Color, Text); - - // Check the bounds - if(W < 0 || X < 0 || X >= giScreenWidth) return 0; - if(X + W > giScreenWidth) W = giScreenWidth - X; - - if(H < 0 || Y < 0 || Y >= giScreenHeight) return 0; - if(Y + H > giScreenHeight) H = giScreenHeight - Y; - - // Handle NULL font (system default monospace) - if( !Font ) Font = &gSystemFont; - - while( *Text ) - { - // Read character - Text += ReadUTF8(Text, &ch); - - // Find (or load) the glyph - glyph = _GetGlyph(Font, ch); - if( !glyph ) continue ; // If not found, just don't render it - - // End render if it will overflow the perscribed range - if( xOfs + glyph->TrueWidth > W ) - break; - - xOfs += glyph->Width; - _RenderGlyph(X + xOfs, Y, glyph, Color); - } - - return xOfs; -} - -void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H) -{ - int w=0, h=0; - uint32_t ch; - tGlyph *glyph; - if( !Font ) Font = &gSystemFont; - - while( *Text ) - { - Text += ReadUTF8(Text, &ch); - glyph = _GetGlyph(Font, ch); - if( !glyph ) continue; - - w += glyph->Width; - if( h < glyph->Height ) h = glyph->Height; - } - - if(W) *W = w; - if(H) *H = h; -} - -tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint) -{ - tGlyph *next = NULL, *prev = NULL; - tGlyph *new; - - // Check for ASCII - if( Codepoint < 128 ) - { - if( Font->AsciiGlyphs[Codepoint] == NULL ) { - Font->AsciiGlyphs[Codepoint] = Font->CacheGlyph(Font, Codepoint); - } - - return Font->AsciiGlyphs[Codepoint]; - } - - // If within the range - if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint ) - { - // Find what end is "closest" - if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint ) - { - // Start from the bottom - for( next = Font->FirstGlyph; - next && next->Codepoint < Codepoint; - prev = next, next = next->Next - ); - - if( next->Codepoint == Codepoint ) - return next; - - } - else - { - // Start at the top - // NOTE: The roles of next and prev are reversed here to allow - // the insert to be able to assume that `prev` is the - // previous entry, and `next` is the next. - for( prev = Font->LastGlyph; - prev && prev->Codepoint > Codepoint; - next = prev, prev = prev->Prev - ); - if( prev->Codepoint == Codepoint ) - return prev; - } - } - else - { - // If below first - if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) { - prev = NULL; - next = Font->FirstGlyph; - } - // Above last - else { - prev = Font->LastGlyph; - next = NULL; - } - } - - // Load new - new = Font->CacheGlyph(Font, Codepoint); - if( !new ) return NULL; - - // Add to list - // - Forward link - if( prev ) { - new->Next = prev->Next; - prev->Next = new; - } - else { - new->Next = Font->FirstGlyph; - Font->FirstGlyph = new; - } - - // - Backlink - if( next ) { - new->Prev = next->Prev; - next->Prev = new; - } - else { - new->Prev = Font->LastGlyph; - Font->LastGlyph = new; - } - - // Return - return new; -} - -/** - */ -void _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color) -{ - int xStart = 0, yStart = 0; - int x, y; - uint32_t *outBuf; - uint8_t *inBuf; - // TODO: Implement - - X += Glyph->OffsetX; - if( X < 0 ) { // If -ve, skip the first -X collums - xStart = -X; - X = 0; - } - - Y += Glyph->OffsetY; - if( Y < 0 ) { // If -ve, skip the first -Y lines - yStart = -Y; - Y = 0; - } - - outBuf = gpScreenBuffer + Y*giScreenWidth + X; - inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth; - - for( y = yStart; y < Glyph->TrueHeight; y ++ ) - { - for( x = xStart; x < Glyph->TrueWidth; x ++ ) - { - outBuf[x] = Video_AlphaBlend( outBuf[x], Color, inBuf[x] ); - } - outBuf += giScreenWidth; - inBuf += Glyph->TrueWidth; - - } -} - -// Load system font (8x16 monospace) -#include "font_8x16.h" - -/* - */ -tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint) -{ - int i; - uint8_t index = 0; - tGlyph *ret; - uint8_t *data; - - _SysDebug("_SystemFont_CacheGlyph: (Font=%p, Codepoint=0x%06x)", Font, Codepoint); - - if( Codepoint < 128 ) { - index = Codepoint; - } - else { - index = '?'; // Unknowns come out as a question mark - } - - _SysDebug(" index = %i", index); - - ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT ); - if( !ret ) { - _SysDebug("ERROR: malloc(%i) failed", sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT); - return NULL; - } - - ret->Codepoint = Codepoint; - - ret->Width = FONT_WIDTH; - ret->Height = FONT_HEIGHT; - - ret->TrueWidth = FONT_WIDTH; - ret->TrueHeight = FONT_HEIGHT; - - ret->OffsetX = 0; - ret->OffsetY = 0; - - data = &VTermFont[index * FONT_HEIGHT]; - - for( i = 0; i < FONT_HEIGHT; i ++ ) - { - ret->Bitmap[ i * 8 + 0 ] = data[i] & (1 << 7) ? 255 : 0; - ret->Bitmap[ i * 8 + 1 ] = data[i] & (1 << 6) ? 255 : 0; - ret->Bitmap[ i * 8 + 2 ] = data[i] & (1 << 5) ? 255 : 0; - ret->Bitmap[ i * 8 + 3 ] = data[i] & (1 << 4) ? 255 : 0; - ret->Bitmap[ i * 8 + 4 ] = data[i] & (1 << 3) ? 255 : 0; - ret->Bitmap[ i * 8 + 5 ] = data[i] & (1 << 2) ? 255 : 0; - ret->Bitmap[ i * 8 + 6 ] = data[i] & (1 << 1) ? 255 : 0; - ret->Bitmap[ i * 8 + 7 ] = data[i] & (1 << 0) ? 255 : 0; - } - - return ret; -} - - -/** - * \fn int ReadUTF8(char *Input, uint32_t *Val) - * \brief Read a UTF-8 character from a string - */ -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 & 0xF1) == 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; -} - - - - diff --git a/Usermode/Applications/axwin2_src/WM/wm.c b/Usermode/Applications/axwin2_src/WM/wm.c deleted file mode 100644 index b0732235..00000000 --- a/Usermode/Applications/axwin2_src/WM/wm.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Acess GUI (AxWin) Version 2 - * By John Hodge (thePowersGang) - * - * Window Manager and Widget Control - */ -#include "common.h" -#include -#include -#include "wm.h" -#include // _SysDebug - -// === IMPORTS === -extern void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H); - -// === PROTOTYPES === -tApplication *AxWin_RegisterClient(tIPC_Type *IPCType, void *Ident, const char *Name); -void AxWin_DeregisterClient(tApplication *App); -tApplication *AxWin_GetClient(tIPC_Type *Method, void *Ident); -tElement *AxWin_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName); -void AxWin_DeleteElement(tElement *Element); -void AxWin_SetFlags(tElement *Element, int Flags); -void AxWin_SetSize(tElement *Element, int Size); -void AxWin_SetText(tElement *Element, const char *Text); - -// === GLOBALS === -// - TODO: Handle windows by having multiple root elements -tElement gWM_RootElement = { - .DebugName = "ROOT" -}; -tWindow *gWM_WindowFirst; -tWindow *gWM_WindowLast; -tApplication *gWM_Applications; - int giWM_MaxAreaX = 0; - int giWM_MaxAreaY = 0; - int giWM_MaxAreaW = -1; - int giWM_MaxAreaH = -1; - -// --- Element type flags -struct { - void (*Init)(tElement *This); - void (*Delete)(tElement *This); - void (*UpdateFlags)(tElement *This); - void (*UpdateSize)(tElement *This); - void (*UpdateText)(tElement *This); -} gaWM_WidgetTypes[MAX_ELETYPES] = { - {NULL, NULL, NULL, NULL, NULL}, // NULL - {NULL, NULL, NULL, NULL, NULL}, // Window - {NULL, NULL, NULL, NULL, NULL} // Box -}; -const int ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]); - -// === CODE === -tApplication *AxWin_RegisterClient(tIPC_Type *Method, void *Ident, const char *Name) -{ - int identlen = Method->GetIdentSize(Ident); - // Structure, empty string, Name, Ident - tApplication *ret = calloc( 1, sizeof(tApplication) + 1 + strlen(Name) + 1 + identlen ); - - // DebugName is empty - - // Name/Title - ret->Name = &ret->MetaElement.DebugName[1]; - strcpy(ret->Name, Name); - // Ident - ret->Ident = ret->Name + strlen(Name) + 1; - memcpy(ret->Ident, Ident, identlen); - // IPC Type - ret->IPCType = Method; - - // Element index - ret->MaxElementIndex = DEFAULT_ELEMENTS_PER_APP; - ret->EleIndex = calloc( 1, ret->MaxElementIndex * sizeof(*ret->EleIndex) ); - - // Add to global list - ret->Next = gWM_Applications; - gWM_Applications = ret; - - // TODO: Inform listeners of the new application - - return ret; -} - -void AxWin_DeregisterClient(tApplication *App) -{ - // TODO: Complete implementing DeregisterClient - tElement *win, *next; - - for( win = App->MetaElement.FirstChild; win; win = next ) - { - next = win->NextSibling; - AxWin_DeleteElement(win); - } - - // TODO: Inform listeners of deleted application - - // Remove from list - { - tApplication *app, *prev = NULL; - for( app = gWM_Applications; app; app = app->Next ) - { - if( app == App ) break; - prev = app; - } - - if( app ) - { - if(prev) - prev->Next = App->Next; - else - gWM_Applications = App->Next; - } - } - - free(App); -} - -/** - * \brief Get an application handle from a client identifier - */ -tApplication *AxWin_GetClient(tIPC_Type *Method, void *Ident) -{ - // TODO: Faster and smarter technique - tApplication *app; - for( app = gWM_Applications; app; app = app->Next ) - { - if( app->IPCType != Method ) continue; - if( Method->CompareIdent( app->Ident, Ident ) != 0 ) continue; - return app; - } - return NULL; -} - -tElement *AxWin_CreateAppWindow(tApplication *App, const char *Name) -{ - tElement *ret; - tWindow *win; - - win = calloc(1, sizeof(tWindow) + 1); - if(!win) return NULL; - - ret = &win->RootElement; - ret->Type = ELETYPE_WINDOW; - ret->Data = win; - ret->Parent = &App->MetaElement; - - // Add to parent list - if(ret->Parent->LastChild) - ret->Parent->LastChild->NextSibling = ret; - ret->Parent->LastChild = ret; - if(!ret->Parent->FirstChild) - ret->Parent->FirstChild = ret; - - ret->Text = strdup(Name); - - return ret; -} - -// --- Widget Creation and Control --- -tAxWin_Element *AxWin_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName) -{ - tElement *ret; - const char *dbgName = DebugName ? DebugName : ""; - - ret = calloc(sizeof(tElement)+strlen(dbgName)+1, 1); - if(!ret) return NULL; - - // Prepare - ret->Type = Type; - strcpy(ret->DebugName, dbgName); - if(Parent == NULL) Parent = &gWM_RootElement; - ret->Parent = Parent; - ret->Flags = Flags; - - // Append to parent's list - if(Parent->LastChild) - Parent->LastChild->NextSibling = ret; - Parent->LastChild = ret; - if(!Parent->FirstChild) Parent->FirstChild = ret; - - ret->PaddingL = 2; - ret->PaddingR = 2; - ret->PaddingT = 2; - ret->PaddingB = 2; - - if( Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[Type].Init ) - gaWM_WidgetTypes[Type].Init(ret); - - WM_UpdateMinDims(ret->Parent); - - return ret; -} - -/** - * \brief Delete an element - */ -void AxWin_DeleteElement(tElement *Element) -{ - tElement *child, *next; - - for(child = Element->FirstChild; child; child = next) - { - next = child->NextSibling; - AxWin_DeleteElement(child); - } - - // TODO: Implement AxWin_DeleteElement - // TODO: Clean up related data. - if( Element->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[Element->Type].Delete ) - gaWM_WidgetTypes[Element->Type].Delete(Element); - - if(Element->Owner) - Element->Owner->EleIndex[ Element->ApplicationID ] = NULL; - - Element->Type = 0; - Element->Owner = 0; - Element->Flags = 0; - - free(Element); -} - -/** - * \brief Alter an element's flags - */ -void AxWin_SetFlags(tElement *Element, int Flags) -{ - // Permissions are handled in the message handler - if(!Element) { - gWM_RootElement.Flags = Flags; - return ; - } - - Element->Flags = Flags; - return ; -} - -/** - * \brief Set the fixed lenghthways size of an element - */ -void AxWin_SetSize(tElement *Element, int Size) -{ - if(!Element) return ; - Element->FixedWith = Size; - return ; -} - -/** - * \brief Set the text field of an element - * \note Used for the image path on ELETYPE_IMAGE - */ -void AxWin_SetText(tElement *Element, const char *Text) -{ - if(!Element) return ; - if(Element->Text) free(Element->Text); - Element->Text = strdup(Text); - - switch(Element->Type) - { - case ELETYPE_IMAGE: - if(Element->Data) free(Element->Data); - Element->Data = Image_Load( Element->Text ); - if(!Element->Data) { - Element->Flags &= ~ELEFLAG_FIXEDSIZE; - return ; - } - - //Element->Flags |= ELEFLAG_FIXEDSIZE; - Element->CachedW = ((tImage*)Element->Data)->Width; - Element->CachedH = ((tImage*)Element->Data)->Height; - - if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) { - Element->MinCross = ((tImage*)Element->Data)->Width; - Element->MinWith = ((tImage*)Element->Data)->Height; - } - else { - Element->MinWith = ((tImage*)Element->Data)->Width; - Element->MinCross = ((tImage*)Element->Data)->Height; - } - break; - - case ELETYPE_TEXT: - { - int w=0, h=0; - Video_GetTextDims(NULL, Element->Text, &w, &h); - if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) { - Element->MinCross = w; - Element->MinWith = h; - } - else { - Element->MinWith = w; - Element->MinCross = h; - } - } - break; - default: // Any other, no special case - break ; - } - - return ; -} diff --git a/Usermode/Applications/axwin2_src/WM/wm.h b/Usermode/Applications/axwin2_src/WM/wm.h deleted file mode 100644 index 5977fd68..00000000 --- a/Usermode/Applications/axwin2_src/WM/wm.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Acess2 Window Manager (AxWin2) - */ -#ifndef _WM_H_ -#define _WM_H_ - -#include -#include "common.h" - -/** - * \brief Number of elements that can be owned by each application - */ -// TODO: Fine tune these values -#define MAX_ELEMENTS_PER_APP 1024 -#define DEFAULT_ELEMENTS_PER_APP 128 - -typedef struct sAxWin_Element tElement; -typedef struct sMenuItem tMenuItem; -typedef struct sWindow tWindow; -typedef struct sApplication tApplication; - -struct sAxWin_Element -{ - enum eElementTypes Type; - - // Element Tree - tElement *Parent; - tElement *FirstChild; - tElement *LastChild; - tElement *NextSibling; - - // Application - tApplication *Owner; //!< Owning application - uint16_t ApplicationID; //!< Index into sApplication::EleIndex - - // User modifiable attributes - short PaddingL, PaddingR; - short PaddingT, PaddingB; - short GapSize; - - uint32_t Flags; - - short FixedWith; //!< Fixed lengthways Size attribute (height) - short FixedCross; //!< Fixed Cross Size attribute (width) - - char *Text; - - // -- Attributes maitained by the element code - // Not touched by the user - short MinWith; //!< Minimum long size - short MinCross; //!< Minimum cross size - void *Data; //!< Per-type data - - // -- Render Cache - short CachedX, CachedY; - short CachedW, CachedH; - - char DebugName[]; -}; - -struct sMenuItem -{ - tMenuItem *Next; - int Flags; - int ID; //!< ID number sent to application - const char *Label; - const char *Right; - tMenuItem *FirstChild; -}; - -struct sWindow -{ - int X, Y, W, H; - void *Icon; - - tApplication *App; - - tWindow *OrderNext; // Render order - - tMenuItem *Menus; - - tElement RootElement; -}; - -struct sApplication -{ - tApplication *Next; - - tIPC_Type *IPCType; - void *Ident; //!< Client Identifier - - char *Name; //!< Application name - - int MaxElementIndex; //!< Number of entries in \a EleIndex - tElement **EleIndex; //!< Array of pointers to elements owned by this application - - tElement MetaElement; //!< Tabs child off this -}; - -// === FUNCTIONS === - -// --- Render -extern void WM_UpdateMinDims(tElement *Element); -extern void WM_UpdateDimensions(tElement *Element, int Pass); -extern void WM_UpdatePosition(tElement *Element); -extern void WM_RenderWidget(tElement *Element); -extern void WM_Update(void); - -#endif diff --git a/Usermode/Applications/axwin2_src/notes.txt b/Usermode/Applications/axwin2_src/notes.txt deleted file mode 100644 index d4090b9c..00000000 --- a/Usermode/Applications/axwin2_src/notes.txt +++ /dev/null @@ -1,3 +0,0 @@ -Applications can have 0-* windows -Windows can have 1-* tabs -Each window has a menu based on a template from the application diff --git a/Usermode/Applications/axwin3_src/Interface/main.c b/Usermode/Applications/axwin3_src/Interface/main.c index e34968c9..fd4ff3f4 100644 --- a/Usermode/Applications/axwin3_src/Interface/main.c +++ b/Usermode/Applications/axwin3_src/Interface/main.c @@ -19,6 +19,7 @@ void create_sidebar(void); void create_mainmenu(void); void create_run_dialog(void); +void mainmenu_run_dialog(void *unused); // === GLOBALS === tHWND gSidebar; @@ -49,6 +50,10 @@ int main(int argc, char *argv[]) create_mainmenu(); create_run_dialog(); + AxWin3_RegisterAction(gSidebar, "Interface>Run", (tAxWin3_HotkeyCallback)mainmenu_run_dialog); +// AxWin3_RegisterAction(gSidebar, "Interface>Terminal", mainmenu_app_terminal); +// AxWin3_RegisterAction(gSidebar, "Interface>TextEdit", mainmenu_app_textedit); + // Idle loop AxWin3_MainLoop(); @@ -130,6 +135,7 @@ void create_mainmenu(void) // -------------------------------------------------------------------- int run_dorun(tAxWin3_Widget *unused) { + _SysDebug("DoRun pressed"); char *cmd = AxWin3_Widget_GetText(gRunInput); _SysDebug("Command string '%s'", cmd); AxWin3_ShowWindow(gRunDialog, 0); diff --git a/Usermode/Applications/axwin3_src/WM/include/wm_hotkeys.h b/Usermode/Applications/axwin3_src/WM/include/wm_hotkeys.h index 44675d21..1a7ca7ef 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_hotkeys.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_hotkeys.h @@ -33,6 +33,7 @@ struct sHotkeyTarget extern void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName); +extern void WM_Hotkey_RegisterAction(const char *ActionName, tWindow *Target, uint16_t Index); extern void WM_Hotkey_KeyDown(uint32_t Scancode); extern void WM_Hotkey_KeyUp(uint32_t Scancode); diff --git a/Usermode/Applications/axwin3_src/WM/ipc.c b/Usermode/Applications/axwin3_src/WM/ipc.c index b3648bb7..cbed7fd1 100644 --- a/Usermode/Applications/axwin3_src/WM/ipc.c +++ b/Usermode/Applications/axwin3_src/WM/ipc.c @@ -13,6 +13,7 @@ #include #include #include +#include #define AXWIN_PORT 4101 @@ -495,7 +496,26 @@ int IPC_Msg_SetWinPos(tIPC_Client *Client, tAxWin_IPCMessage *Msg) int IPC_Msg_RegisterAction(tIPC_Client *Client, tAxWin_IPCMessage *Msg) { + tIPCMsg_RegAction *info = (void*)Msg->Data; + tWindow *win; + ASSERT(Msg->ID == IPCMSG_REGACTION); + + if( Msg->Size < sizeof(*info) + 1 ) + return -1; + + win = IPC_int_GetWindow(Client, Msg->Window); + if(!win) return 1; + + if( strnlen(info->Action, Msg->Size - sizeof(*info)) == Msg->Size - sizeof(*info) ) + return 1; + + _SysDebug("RegisterAction %p:%i [%i]\"%s\"", + Client, Msg->Window, info->Index, info->Action + ); + + WM_Hotkey_RegisterAction(info->Action, win, info->Index); + return 0; } diff --git a/Usermode/Applications/axwin3_src/WM/main.c b/Usermode/Applications/axwin3_src/WM/main.c index 7aa5534a..0996f909 100644 --- a/Usermode/Applications/axwin3_src/WM/main.c +++ b/Usermode/Applications/axwin3_src/WM/main.c @@ -9,6 +9,7 @@ #include #include #include +#include // === IMPORTS === extern void Video_Setup(void); @@ -18,6 +19,7 @@ extern int Renderer_Widget_Init(void); extern int Renderer_Background_Init(void); extern int Renderer_Framebuffer_Init(void); extern void WM_Update(void); +extern void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName); // === PROTOTYPES === void ParseCommandline(int argc, char **argv); @@ -63,6 +65,11 @@ int main(int argc, char *argv[]) Renderer_Background_Init(); Renderer_Framebuffer_Init(); WM_Initialise(); + + // TODO: Config + uint32_t keys[4]; + keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_r; + WM_Hotkey_Register(2, keys, "Interface>Run"); // Spawn interface root if( clone(CLONE_VM, 0) == 0 ) diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget.c b/Usermode/Applications/axwin3_src/WM/renderers/widget.c index 7668cbd6..46b3198a 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/widget.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget.c @@ -552,6 +552,34 @@ void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg) // } } +int Widget_GetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg) +{ + if( Len < sizeof(*Msg) ) + return 0; + if( Len > sizeof(*Msg) ) + return 1; // Pass to user + + const char *text = NULL; + tElement *ele = Widget_GetElementById(Info, Msg->WidgetID); + if(ele) + text = ele->Text; + + char buf[sizeof(tWidgetMsg_SetText) + strlen(text?text:"") + 1]; + tWidgetMsg_SetText *omsg = (void*)buf; + + if( text ) { + omsg->WidgetID = Msg->WidgetID; + strcpy(omsg->Text, text); + } + else { + omsg->WidgetID = -1; + omsg->Text[0] = 0; + } + + WM_SendMessage(Info->RootElement.Window, Info->RootElement.Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf); + return 0; +} + int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data) { tWidgetWin *info = Target->RendererInfo; @@ -691,6 +719,8 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void case MSG_WIDGET_SETTEXT: Widget_SetText(info, Len, Data); return 0; + case MSG_WIDGET_GETTEXT: + return Widget_GetText(info, Len, Data); // default: diff --git a/Usermode/Applications/axwin3_src/WM/wm_hotkeys.c b/Usermode/Applications/axwin3_src/WM/wm_hotkeys.c index 3fbe4f76..bdea09c5 100644 --- a/Usermode/Applications/axwin3_src/WM/wm_hotkeys.c +++ b/Usermode/Applications/axwin3_src/WM/wm_hotkeys.c @@ -40,6 +40,11 @@ void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName) h->Target = (void*)( h->Keys + nKeys ); strcpy((char*)h->Target, ActionName); memcpy(h->Keys, Keys, nKeys * sizeof(uint32_t)); + + h->Next = NULL; + if( gpWM_Hotkeys ) + gpWM_Hotkeys->Next = h; + gpWM_Hotkeys = h; } void WM_Hotkey_RegisterAction(const char *ActionName, tWindow *Target, uint16_t Index) @@ -82,6 +87,8 @@ void WM_Hotkey_KeyUp(uint32_t Scancode) { _UnsetKey(Scancode); + // Ensure that hotkeys are triggered on the longest sequence + // (so Win-Shift-R doesn't trigger Win-R if shift is released) if( !gbWM_HasBeenKeyDown ) return ; @@ -94,7 +101,8 @@ void WM_Hotkey_KeyUp(uint32_t Scancode) if( _IsKeySet(hk->Keys[i]) ) continue ; break; } - if( i == hk->nKeys ) + _SysDebug("%i/%i satisfied for %s", i, hk->nKeys, hk->Target); + if( i != hk->nKeys ) continue ; // Fire shortcut @@ -108,6 +116,7 @@ void WM_Hotkey_KeyUp(uint32_t Scancode) void WM_Hotkey_FireEvent(const char *Target) { +// _SysDebug("WM_Hotkey_FireEvent: (%s)", Target); // - Internal events (Alt-Tab, Close, Maximize, etc...) // TODO: Internal event handling @@ -133,11 +142,13 @@ void WM_Hotkey_FireEvent(const char *Target) static void _SetKey(uint32_t sc) { +// _SysDebug("_SetKey: (%x)", sc); if( sc >= MAX_STATE_SCANCODE ) return; gWM_KeyStates[sc/8] |= 1 << (sc % 8); } static void _UnsetKey(uint32_t sc) { +// _SysDebug("_UnsetKey: (%x)", sc); if( sc >= MAX_STATE_SCANCODE ) return; gWM_KeyStates[sc/8] &= ~(1 << (sc % 8)); } diff --git a/Usermode/Applications/axwin3_src/WM/wm_input.c b/Usermode/Applications/axwin3_src/WM/wm_input.c index 751bcbbe..5f6ef853 100644 --- a/Usermode/Applications/axwin3_src/WM/wm_input.c +++ b/Usermode/Applications/axwin3_src/WM/wm_input.c @@ -34,8 +34,8 @@ tWindow *WM_int_GetWindowAtPos(int X, int Y) for(win = ret->FirstChild; win; win = win->NextSibling) { if( !(win->Flags & WINFLAG_SHOW) ) continue ; - if( X < win->X || X >= win->X + win->W ) continue; - if( Y < win->Y || Y >= win->Y + win->H ) continue; + if( X < win->X || X >= win->X + win->RealW ) continue; + if( Y < win->Y || Y >= win->Y + win->RealH ) continue; next_win = win; // Overwrite as we want the final rendered window } } diff --git a/Usermode/Applications/axwin3_src/include/ipcmessages.h b/Usermode/Applications/axwin3_src/include/ipcmessages.h index e7424fe3..6e61ba8e 100644 --- a/Usermode/Applications/axwin3_src/include/ipcmessages.h +++ b/Usermode/Applications/axwin3_src/include/ipcmessages.h @@ -17,6 +17,7 @@ typedef struct sIPCMsg_CreateWin tIPCMsg_CreateWin; typedef struct sIPCMsg_Boolean tIPCMsg_Boolean; typedef struct sIPCMsg_SetWindowPos tIPCMsg_SetWindowPos; typedef struct sIPCMsg_SendMsg tIPCMsg_SendMsg; +typedef struct sIPCMsg_RegAction tIPCMsg_RegAction; typedef struct sIPCMsg_GetDisplayDims tIPCMsg_GetDisplayDims; typedef struct sIPCMsg_RetDisplayDims tIPCMsg_RetDisplayDims; @@ -73,6 +74,12 @@ struct sIPCMsg_SetWindowPos uint8_t bSetDims; }; +struct sIPCMsg_RegAction +{ + uint16_t Index; + char Action[]; +}; + struct sIPCMsg_GetDisplayDims { uint16_t DisplayID; diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c index 875f14b8..450e4b4f 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c @@ -8,7 +8,6 @@ #include #include #include "include/internal.h" -#include "include/ipc.h" #include #include #include @@ -232,23 +231,20 @@ char *AxWin3_Widget_GetText(tAxWin3_Widget *Widget) { char buf[sizeof(tWidgetMsg_SetText)]; tWidgetMsg_SetText *msg = (void*)buf; - tAxWin_IPCMessage *retmsg; - char *ret; + size_t retmsg_size; msg->WidgetID = Widget->ID; AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf); - retmsg = AxWin3_int_WaitIPCMessage(MSG_WIDGET_GETTEXT); - msg = (void*)retmsg->Data; - - if( retmsg->Size < sizeof(*msg) ) { - free(retmsg); + msg = AxWin3_WaitMessage(Widget->Window, MSG_WIDGET_GETTEXT, &retmsg_size); + if( retmsg_size < sizeof(*msg) ) { + free(msg); return NULL; } - ret = strndup(msg->Text, retmsg->Size - sizeof(*msg)); - free(retmsg); + char *ret = strndup(msg->Text, retmsg_size - sizeof(*msg)); + free(msg); return ret; } diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c index 8b138606..4a6d8d33 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c @@ -10,8 +10,10 @@ #include #include "include/internal.h" #include "include/ipc.h" +#include -#define WINDOWS_PER_ALLOC (63) +#define WINDOWS_PER_ALLOC (64-1) // -1 to make it 64 pointers (+ Next) +#define MAX_HOTKEYS 32 typedef struct sWindowBlock tWindowBlock; @@ -28,6 +30,7 @@ struct sWindowBlock int giAxWin3_LowestFreeWinID; int giAxWin3_HighestUsedWinID; tWindowBlock gAxWin3_WindowList; +tAxWin3_HotkeyCallback gAxWin3_Hotkeys[MAX_HOTKEYS]; // === CODE === tWindow *AxWin3_int_CreateWindowStruct(uint32_t ServerID, int ExtraBytes) @@ -198,7 +201,26 @@ void AxWin3_int_HandleMessage(tAxWin_IPCMessage *Msg) return ; } _SysDebug("IPC Message 0x%x - %i bytes", info->ID, info->Length); - dest->Handler(dest, info->ID, info->Length, info->Data); + + if( dest->Handler(dest, info->ID, info->Length, info->Data) ) + ; + else { + switch( info->ID ) + { + case WNDMSG_HOTKEY: { + const struct sWndMsg_Hotkey *mi = (void*)info->Data; + if( mi->ID >= MAX_HOTKEYS ) + ; // TODO: Error when hotkey is out of range + else if( gAxWin3_Hotkeys[mi->ID] == 0 ) + _SysDebug("--- Unmapped hotkey ID %i fired", mi->ID); + else + gAxWin3_Hotkeys[mi->ID](); + }break; + default: + _SysDebug("--- Unhandled SENDMSG %i", info->ID); + break; + } + } break; } default: _SysDebug("Unknow message ID %i", Msg->ID); @@ -235,6 +257,32 @@ void AxWin3_SendMessage(tHWND Window, tHWND Destination, int Message, int Length free(msg); } +void *AxWin3_WaitMessage(tHWND Window, int MessageID, size_t *Length) +{ + tAxWin_IPCMessage *msg; + + for( ;; ) + { + msg = AxWin3_int_WaitIPCMessage(IPCMSG_SENDMSG); + if( msg->Window != AxWin3_int_GetWindowID(Window) ) { + AxWin3_int_HandleMessage(msg); + continue ; + } + tIPCMsg_SendMsg *info = (void*)msg->Data; + if( info->ID != MessageID ) { + AxWin3_int_HandleMessage(msg); + continue ; + } + + *Length = info->Length; + void *ret = malloc(info->Length); + memcpy(ret, info->Data, info->Length); + free(msg); + + return ret; + } +} + void AxWin3_FocusWindow(tHWND Window) { tAxWin_IPCMessage *msg; @@ -326,3 +374,28 @@ void AxWin3_ResizeWindow(tHWND Window, short W, short H) free(msg); } +int AxWin3_RegisterAction(tHWND Window, const char *Action, tAxWin3_HotkeyCallback cb) +{ + int i; + for( i = 0; i < MAX_HOTKEYS; i ++ ) + { + if( gAxWin3_Hotkeys[i] == NULL ) + { + tAxWin_IPCMessage *msg; + struct sIPCMsg_RegAction *info; + gAxWin3_Hotkeys[i] = cb; + + msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_REGACTION, 0, sizeof(*info)+strlen(Action)+1); + info = (void*)msg->Data; + + info->Index = i; + strcpy(info->Action, Action); + + AxWin3_int_SendIPCMessage(msg); + free(msg); + return i; + } + } + return -1; +} + diff --git a/Usermode/Libraries/Makefile.tpl b/Usermode/Libraries/Makefile.tpl index 54b203ab..7687f2e1 100644 --- a/Usermode/Libraries/Makefile.tpl +++ b/Usermode/Libraries/Makefile.tpl @@ -37,7 +37,7 @@ endif $(_BIN): $(OBJ) $(_LIBS) @mkdir -p $(dir $(_BIN)) @echo [LD] -o $(BIN) $(OBJ) - @$(LD) $(LDFLAGS) -o $(_BIN) $(OBJ) + $(LD) $(LDFLAGS) -o $(_BIN) $(OBJ) $(shell $(CC) -print-libgcc-file-name) @$(DISASM) -S $(_BIN) > $(_OBJPREFIX)$(BIN).dsm $(_OBJPREFIX)%.o: %.c diff --git a/Usermode/Libraries/acess.ld_src/acess_armv6.ld.h b/Usermode/Libraries/acess.ld_src/acess_armv6.ld.h new file mode 100644 index 00000000..0ea7f902 --- /dev/null +++ b/Usermode/Libraries/acess.ld_src/acess_armv6.ld.h @@ -0,0 +1,235 @@ +/* Script for -z combreloc: combine and sort reloc sections */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", + "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SEARCH_DIR(__LIBDIR) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000); + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rel.plt : + { + *(.rel.plt) + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + PROVIDE_HIDDEN(__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN(__exidx_end = .); + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data : + { + __data_start = . ; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + _bss_end__ = . ; __bss_end__ = . ; + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + __end__ = . ; + _end = .; PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo .zdebug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames .zdebug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges .zdebug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames .zdebug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.* .zdebug_info) } + .debug_abbrev 0 : { *(.debug_abbrev .zdebug_abbrev) } + .debug_line 0 : { *(.debug_line .zdebug_line) } + .debug_frame 0 : { *(.debug_frame .zdebug_frame) } + .debug_str 0 : { *(.debug_str .zdebug_str) } + .debug_loc 0 : { *(.debug_loc .zdebug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo .zdebug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames .zdebug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames .zdebug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames .zdebug_typenames) } + .debug_varnames 0 : { *(.debug_varnames .zdebug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes .zdebug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges .zdebug_ranges) } + .stack 0x80000 : + { + _stack = .; + *(.stack) + } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} + + diff --git a/Usermode/Libraries/ld-acess.so_src/Makefile b/Usermode/Libraries/ld-acess.so_src/Makefile index 44af24a9..d451b2c1 100644 --- a/Usermode/Libraries/ld-acess.so_src/Makefile +++ b/Usermode/Libraries/ld-acess.so_src/Makefile @@ -20,7 +20,7 @@ include ../Makefile.tpl # create libld-acess.so $(_XBIN): $(_OBJPREFIX)_stublib.o @echo [LD] -o -shared libld-acess.so - $(LD) -shared -o $@ $< + $(LD) -shared -o $@ $< $(LDFLAGS) # @$(LD) $(LDFLAGS) -o $@ $(OBJ) diff --git a/Usermode/Libraries/ld-acess.so_src/_stublib.c b/Usermode/Libraries/ld-acess.so_src/_stublib.c index abf80435..11362261 100644 --- a/Usermode/Libraries/ld-acess.so_src/_stublib.c +++ b/Usermode/Libraries/ld-acess.so_src/_stublib.c @@ -14,6 +14,7 @@ int _errno; #include "arch/syscalls.s.h" // libgcc functions +#if 0 uint64_t __udivdi3(uint64_t Num, uint64_t Den){return 0;} uint64_t __umoddi3(uint64_t Num, uint64_t Den){return 0;} @@ -21,6 +22,8 @@ int32_t __divsi3(int32_t Num, int32_t Den){return 0;} int32_t __modsi3(int32_t Num, int32_t Den){return 0;} uint32_t __udivsi3(uint32_t Num, uint32_t Den){return 0;} uint32_t __umodsi3(uint32_t Num, uint32_t Den){return 0;} +#endif void *_crt0_exit_handler; +void abort(void){} diff --git a/Usermode/Libraries/ld-acess.so_src/arch/armv6.S.h b/Usermode/Libraries/ld-acess.so_src/arch/armv6.S.h new file mode 100644 index 00000000..35643926 --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/arch/armv6.S.h @@ -0,0 +1,137 @@ +// +// Acess2 ARMv7 - System Calls +// + +.globl _start +.extern SoMain +_start: + pop {r0} + ldm sp, {r1,r2,r3} + bl SoMain + + mov r4, r0 + + pop {r0,r1,r2} + blx r4 + + b _exit + +@ Stupid GCC +.globl __ucmpdi2 +__ucmpdi2: + cmp r0, r2 + movmi r0, #0 + movmi pc, lr + movhi r0, #2 + movhi pc, lr + cmp r1, r2 + movmi r0, #0 + movmi pc, lr + movhi r0, #2 + movhi pc, lr + mov r0, #1 + mov pc, lr + +@ Well, can't blame it +@ - Clear the instruction cache +.globl __clear_cache +__clear_cache: + svc #0x1001 + mov pc, lr + +@ DEST +@ SRC +@_memcpy: +@ push rbp +@ mov rbp, rsp +@ +@ ; RDI - First Param +@ ; RSI - Second Param +@ mov rcx, rdx ; RDX - Third +@ rep movsb +@ +@ pop rbp +@ ret +@ +.globl _errno +_errno: .long 0 @ Placed in .text, to allow use of relative addressing + +.macro syscall0 _name, _num +.globl \_name +\_name: + push {lr} + svc #\_num + str r2, _errno + pop {pc} +.endm + +.macro syscall5 _name, _num +.globl \_name +\_name: + push {r4, lr} + ldr r4, [sp,#8] + svc #\_num + str r2, _errno + pop {r4, pc} +.endm + +.macro syscall6 _name, _num +.globl \_name +\_name: + push {r4,r5,lr} + ldr r4, [sp,#12] + ldr r5, [sp,#16] + svc #\_num + str r2, _errno + pop {r4,r5,pc} +.endm + +#define SYSCALL0(_name,_num) syscall0 _name, _num +#define SYSCALL1(_name,_num) SYSCALL0(_name, _num) +#define SYSCALL2(_name,_num) SYSCALL0(_name, _num) +#define SYSCALL3(_name,_num) SYSCALL0(_name, _num) +#define SYSCALL4(_name,_num) SYSCALL0(_name, _num) +// TODO: 5/6 need special handling, because the args are on the stack +#define SYSCALL5(_name,_num) syscall5 _name, _num +#define SYSCALL6(_name,_num) syscall6 _name, _num + +// Override the clone syscall +#define _exit _exit_raw +#define _clone _clone_raw +#include "syscalls.s.h" +#undef _exit +#undef _clone + +.globl _clone +_clone: + push {r4} + mov r4, r1 + svc #SYS_CLONE + str r2, _errno + tst r4, r4 + beq _clone_ret + @ If in child, set SP + tst r0,r0 + movne sp, r4 +_clone_ret: + pop {r4} + mov pc, lr + +.globl _exit +_exit: + svc #0 + b . + +.globl abort +abort: + mov r0, #0 + svc #0 + b . + +.globl __exidx_start +__exidx_start: + b . +.globl __exidx_end +__exidx_end: + b . + diff --git a/Usermode/Libraries/ld-acess.so_src/arch/armv6.ld b/Usermode/Libraries/ld-acess.so_src/arch/armv6.ld new file mode 100644 index 00000000..7f1b3c83 --- /dev/null +++ b/Usermode/Libraries/ld-acess.so_src/arch/armv6.ld @@ -0,0 +1,69 @@ +ENTRY(_start) +OUTPUT_FORMAT(elf32-littlearm) + +SECTIONS { + . = 0x6FFF0000; + gLinkedBase = .; + . += SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + + .text : AT(ADDR(.text)) { + code = .; + *(.text) + *(.rodata*) + PROVIDE_HIDDEN(__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN(__exidx_end = .); + } + + .data ALIGN (0x1000) : AT(ADDR(.data)) { + data = .; + *(.data) + } + + .bss ALIGN (0x1000) : AT(ADDR(.bss)) { + _sbss = .; + *(COMMON) + *(.bss) + _ebss = .; + bss = .; + } + _end = .; +} diff --git a/Usermode/Libraries/ld-acess.so_src/export.c b/Usermode/Libraries/ld-acess.so_src/export.c index 1062d7e4..32f70d22 100644 --- a/Usermode/Libraries/ld-acess.so_src/export.c +++ b/Usermode/Libraries/ld-acess.so_src/export.c @@ -23,6 +23,7 @@ const struct { } caLocalExports[] = { EXP(gLoadedLibraries), EXP(_exit), + EXP(_errno), EXP(clone), EXP(kill), EXP(yield), @@ -75,12 +76,14 @@ const struct { EXP(_SysAllocate), EXP(_SysDebug), +#if 0 EXP(__umoddi3), EXP(__udivdi3), EXP(__divsi3), EXP(__modsi3), EXP(__udivsi3), EXP(__umodsi3) +#endif }; const int ciNumLocalExports = sizeof(caLocalExports)/sizeof(caLocalExports[0]); diff --git a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/intdefs.h b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/intdefs.h index 46a06c40..36086d09 100644 --- a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/intdefs.h +++ b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/intdefs.h @@ -22,7 +22,7 @@ typedef __uint32_t __uintptr_t; #elif defined(ARCHDIR_is_x86_64) typedef __int64_t __intptr_t; typedef __uint64_t __uintptr_t; -#elif defined(ARCHDIR_is_armv7) +#elif defined(ARCHDIR_is_armv7) | defined(ARCHDIR_is_armv6) typedef __int32_t __intptr_t; typedef __uint32_t __uintptr_t; #else diff --git a/Usermode/Libraries/ld-acess.so_src/lib.c b/Usermode/Libraries/ld-acess.so_src/lib.c index da37dea0..06721026 100644 --- a/Usermode/Libraries/ld-acess.so_src/lib.c +++ b/Usermode/Libraries/ld-acess.so_src/lib.c @@ -112,6 +112,7 @@ uint64_t __divmod64(uint64_t Num, uint64_t Den, uint64_t *Rem) return ret; } +#if 0 uint32_t __divmod32(uint32_t Num, uint32_t Den, uint32_t *Rem) { uint32_t ret = 0, add = 1; @@ -198,4 +199,5 @@ uint32_t __umodsi3(uint32_t Num, uint32_t Den) __divmod32(Num, Den, &ret); return ret; } +#endif diff --git a/Usermode/Libraries/libaxwin2.so_src/Makefile b/Usermode/Libraries/libaxwin2.so_src/Makefile deleted file mode 100644 index 240646b7..00000000 --- a/Usermode/Libraries/libaxwin2.so_src/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Acess 2 - AxWin GUI Library -# - -include ../Makefile.cfg - -CPPFLAGS += -CFLAGS += -Wall -LDFLAGS += -lc -soname libaxwin2.so - -OBJ = main.o messages.o -BIN = libaxwin2.so - -include ../Makefile.tpl diff --git a/Usermode/Libraries/libaxwin2.so_src/common.h b/Usermode/Libraries/libaxwin2.so_src/common.h deleted file mode 100644 index 4e80c7f4..00000000 --- a/Usermode/Libraries/libaxwin2.so_src/common.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * AxWin Window Manager Interface Library - * By John Hodge (thePowersGang) - * This file is published under the terms of the Acess Licence. See the - * file COPYING for details. - * - * common.h - Internal Variable and Constant definitions - */ -#ifndef _COMMON_H_ -#define _COMMON_H_ - -// === Includes === -#include -#include -#include - -// === Constants === -enum eAxWin_Modes -{ - AXWIN_MODE_IPC -}; - -// === Variables === -extern int giAxWin_Mode; -extern int giAxWin_PID; - -#endif diff --git a/Usermode/Libraries/libaxwin2.so_src/include_exp/axwin2/axwin.h b/Usermode/Libraries/libaxwin2.so_src/include_exp/axwin2/axwin.h deleted file mode 100644 index 77db620a..00000000 --- a/Usermode/Libraries/libaxwin2.so_src/include_exp/axwin2/axwin.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - * \file axwin2/axwin.h - * \author John Hodge (thePowersGang) - * \brief AxWin Core functions - */ -#ifndef _AXWIN2_AXWIN_H -#define _AXWIN2_AXWIN_H - -#include -#include - -#include - -// === Core Types === -typedef struct sAxWin_Element tAxWin_Element; -typedef int tAxWin_MessageCallback(tAxWin_Message *); - -// === Functions === -extern int AxWin_Register(const char *ApplicationName, tAxWin_MessageCallback *DefaultHandler); -extern tAxWin_Element *AxWin_CreateWindow(const char *TabTitle); -extern tAxWin_Element *AxWin_AddMenuItem(tAxWin_Element *Parent, const char *Label, int Message); - -extern int AxWin_MessageLoop(void); -extern int AxWin_SendMessage(tAxWin_Message *Message); -extern tAxWin_Message *AxWin_WaitForMessage(void); -extern int AxWin_HandleMessage(tAxWin_Message *Message); - -// === Window Control === - -extern tAxWin_Element *AxWin_CreateElement(tAxWin_Element *Parent, int ElementType, int Flags, const char *DebugName); -extern void AxWin_SetFlags(tAxWin_Element *Element, int Flags); -extern void AxWin_SetText(tAxWin_Element *Element, const char *Text); -extern void AxWin_SetSize(tAxWin_Element *Element, int Size); -extern void AxWin_DeleteElement(tAxWin_Element *Element); - -// === CONSTANTS === -enum eElementFlags -{ - /** - * \brief Rendered - * - * If set, the element will be ignored in calculating sizes and - * rendering. - */ - ELEFLAG_NORENDER = 0x001, - /** - * \brief Element visibility - * - * If set, the element is not drawn (but still is used for size calculations) - */ - ELEFLAG_INVISIBLE = 0x002, - - /** - * \brief Position an element absulutely (ignored in size calcs) - */ - ELEFLAG_ABSOLUTEPOS = 0x004, - - /** - * \brief Fixed size element - */ - ELEFLAG_FIXEDSIZE = 0x008, - - /** - * \brief Element "orientation" - * - * Vertical means that the children of this element are stacked, - * otherwise they list horizontally - */ - ELEFLAG_VERTICAL = 0x010,// ELEFLAG_HORIZONTAL = 0x000, - /** - * \brief Action for text that overflows - */ - ELEFLAG_WRAP = 0x020,// ELEFLAG_NOWRAP = 0x000, - /** - * \brief Cross size action - * - * If this flag is set, the element will only be as large (across - * its parent) as is needed to encase the contents of the element. - * Otherwise, the element will expand to fill all avaliable space. - */ - ELEFLAG_NOEXPAND = 0x040, - - /** - * \brief With (length) size action - * If this flag is set, the element will only be as large as - * is required along it's parent - */ - ELEFLAG_NOSTRETCH = 0x080, - - /** - * \brief Center alignment - */ - ELEFLAG_ALIGN_CENTER= 0x100, - /** - * \brief Right/Bottom alignment - * - * If set, the element aligns to the end of avaliable space (instead - * of the beginning) - */ - ELEFLAG_ALIGN_END = 0x200 -}; - -#define ELEFLAG_WINDOW_MAXIMISED 0x10000 - -/** - */ -enum eElementTypes -{ - ELETYPE_NONE, - - ELETYPE_WINDOW, //!< Window root element - - ELETYPE_BOX, //!< Content box (invisible in itself) - ELETYPE_TABBAR, //!< Tab Bar - ELETYPE_TOOLBAR, //!< Tool Bar - - ELETYPE_BUTTON, //!< Push Button - - ELETYPE_TEXT, //!< Text - ELETYPE_IMAGE, //!< Image - - ELETYPE_SPACER, //!< Visual Spacer (horizontal / vertical rule) - - MAX_ELETYPES = 0x100 -}; - -#endif diff --git a/Usermode/Libraries/libaxwin2.so_src/include_exp/axwin2/messages.h b/Usermode/Libraries/libaxwin2.so_src/include_exp/axwin2/messages.h deleted file mode 100644 index 61536f35..00000000 --- a/Usermode/Libraries/libaxwin2.so_src/include_exp/axwin2/messages.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * \file messages.h - * \author John Hodge (thePowersGang) - * \brief AxWin Control Messages and structures - */ -#ifndef _AXWIN_MESSAGES_H -#define _AXWIN_MESSAGES_H - -#include - -typedef struct sAxWin_Message tAxWin_Message; -typedef struct sAxWin_RetMsg tAxWin_RetMsg; - -// Higherarchy: -// - HANDLE -// + ELEMENT -// > DIALOG -// > TAB - -/** - * \brief Message IDs - */ -enum eAxWin_Messages -{ - // Client->Server Requests - MSG_SREQ_PING, - // - Windows - MSG_SREQ_REGISTER, // bool (char[] Name) - Registers this PID with the Window Manager - - MSG_SREQ_ADDWIN, // ELEMENT (char[] Name) - Adds a tab to the window - - MSG_SREQ_SETICON, // void (TAB Tab, char[] IconURI) - Set the icon of a tab (or application) - - MSG_SREQ_NEWDIALOG, // DIALOG (TAB Parent, char[] Name) - Creates a dialog - MSG_SREQ_DELDIALOG, // void (DIALOG Dialog) - Closes a dialog - - MSG_SREQ_SETNAME, // void (ELEMENT Element, char[] Name) - MSG_SREQ_GETNAME, // char[] (ELEMENT Element) - - // - Builtin Elements - MSG_SREQ_INSERT, // ELEMENT (ELEMENT Parent, eAxWin_Controls Type, u32 Flags) - MSG_SREQ_DELETE, // void (ELEMENT Element) - - // - Drawing - // All drawing functions take an ELEMENT as their first parameter. - // This must be either a Window or Canvas control - MSG_SREQ_SETCOL, - MSG_SREQ_PSET, - MSG_SREQ_LINE, MSG_SREQ_CURVE, - MSG_SREQ_RECT, MSG_SREQ_FILLRECT, - MSG_SREQ_RIMG, MSG_SREQ_SIMG, // Register/Set Image - MSG_SREQ_SETFONT, MSG_SREQ_PUTTEXT, - - // - Callback Registration - - // - WM Control - MSG_SREQ_SET_MAXIMIZE_AREA, // void (uint16_t X, Y, W, H) - - // Server->Client Responses - MSG_SRSP_VERSION, - MSG_SRSP_RETURN, // {int RequestID, void[] Return Value} - Returns a value from a server request - - NUM_MSG -}; - -// --- Server Requests (Requests from the client of the server) -/** - * \brief Server Request - Ping (Get Server Version) - */ -struct sAxWin_SReq_Ping -{ -}; - -/** - * \brief Server Request - New Window - * \see eAxWin_Messages.MSG_SREQ_NEWWINDOW - */ -struct sAxWin_SReq_NewWindow -{ - uint16_t X, Y, W, H; - uint32_t Flags; -}; - -struct sAxWin_SReq_NewElement -{ - uint16_t Parent; - uint16_t Type; - uint32_t Flags; -}; - - -// --- Server Responses -/** - * \brief Server Response - Pong - * \see eAxWin_Messages.MSG_SRSP_PONG - */ -struct sAxWin_SRsp_Version -{ - uint8_t Major; - uint8_t Minor; - uint16_t Build; -}; - - -// === Core Message Structure -/** - * \brief Overarching Message Structure - * \note sizeof(tAxWin_Message) is never valid - */ -struct sAxWin_Message -{ - uint32_t Source; - uint16_t ID; - uint16_t Size; // Size of data - char Data[]; -}; - -struct sAxWin_RetMsg -{ - uint16_t ReqID; - uint16_t Rsvd; - uint32_t Value; -}; - -#endif diff --git a/Usermode/Libraries/libaxwin2.so_src/main.c b/Usermode/Libraries/libaxwin2.so_src/main.c deleted file mode 100644 index de08442f..00000000 --- a/Usermode/Libraries/libaxwin2.so_src/main.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * AxWin Window Manager Interface Library - * By John Hodge (thePowersGang) - * This file is published under the terms of the Acess Licence. See the - * file COPYING for details. - * - * main.c - Library Initialisation - */ -#include "common.h" -#include - -// === GLOBALS === - int giAxWin_Mode = 0; - int giAxWin_PID = 9; // HACK! -tAxWin_MessageCallback *gAxWin_DefaultCallback; - -// === CODE === -int SoMain() -{ - return 0; -} - -tAxWin_Message *AxWin_int_SendAndWait(int RetID, tAxWin_Message *Message) -{ - tAxWin_Message *msg; - tAxWin_RetMsg *rmsg; - - AxWin_SendMessage(Message); - - for(;;) - { - msg = AxWin_WaitForMessage(); - - rmsg = (void*)msg->Data; - if(msg->ID == MSG_SRSP_RETURN && rmsg->ReqID == Message->ID ) - break; - - AxWin_HandleMessage(msg); - free(msg); - } - - return msg; -} - -int AxWin_Register(const char *Name, tAxWin_MessageCallback *DefaultCallback) -{ - tAxWin_Message req; - tAxWin_Message *msg; - int ret; - int len = strlen(Name); - - req.ID = MSG_SREQ_REGISTER; - req.Size = 1 + (len+1)/4; - strcpy(req.Data, Name); - - msg = AxWin_int_SendAndWait(MSG_SRSP_RETURN, &req); - ret = ((tAxWin_RetMsg*)msg->Data)->Value; - free(msg); - - gAxWin_DefaultCallback = DefaultCallback; - - return !!ret; -} - -tAxWin_Element *AxWin_CreateWindow(const char *Title) -{ - tAxWin_Message req; - tAxWin_Message *msg; - tAxWin_Element *ret; - int len = strlen(Title); - - req.ID = MSG_SREQ_ADDWIN; - req.Size = 1 + (len+1)/4; - strcpy(req.Data, Title); - - msg = AxWin_int_SendAndWait(MSG_SRSP_RETURN, &req); - ret = (tAxWin_Element*) ((tAxWin_RetMsg*)msg->Data)->Value; - free(msg); - - return ret; -} - -tAxWin_Element *AxWin_AddMenuItem(tAxWin_Element *Parent, const char *Label, int Message) -{ - return NULL; -} diff --git a/Usermode/Libraries/libaxwin2.so_src/messages.c b/Usermode/Libraries/libaxwin2.so_src/messages.c deleted file mode 100644 index a314703c..00000000 --- a/Usermode/Libraries/libaxwin2.so_src/messages.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * AxWin Window Manager Interface Library - * By John Hodge (thePowersGang) - * This file is published under the terms of the Acess Licence. See the - * file COPYING for details. - * - * messages.c - Message Handling - */ -#include "common.h" - -// === PROTOTYPES === - int AxWin_MessageLoop(); -tAxWin_Message *AxWin_WaitForMessage(); - int AxWin_HandleMessage(tAxWin_Message *Message); - -// === === - -// === CODE === -int AxWin_SendMessage(tAxWin_Message *Message) -{ - switch(giAxWin_Mode) - { - case AXWIN_MODE_IPC: - SysSendMessage(giAxWin_PID, Message->Size*4, Message); - break; - default: - break; - } - return 0; -} - -/** - * \brief Loop forever, checking and waiting for messages - */ -int AxWin_MessageLoop() -{ - tAxWin_Message *msg; - int ret; - for(;;) - { - msg = AxWin_WaitForMessage(); - ret = AxWin_HandleMessage(msg); - - if(ret < 0) return 0; - } - return 0; -} - -/** - * \brief Wait for a message - */ -tAxWin_Message *AxWin_WaitForMessage() -{ - int length; - pid_t src; - tAxWin_Message *ret = NULL; - - switch( giAxWin_Mode ) - { - case AXWIN_MODE_IPC: - while( (length = SysGetMessage(&src, NULL)) == 0 ) sleep(); - ret = malloc(length); - SysGetMessage(NULL, ret); - break; - default: - break; - } - return ret; -} - -/** - * \brief Handles a recieved message - */ -int AxWin_HandleMessage(tAxWin_Message *Message) -{ - switch(Message->ID) - { - default: return 0; - } -} diff --git a/Usermode/Libraries/libaxwin2.so_src/windows.c b/Usermode/Libraries/libaxwin2.so_src/windows.c deleted file mode 100644 index efb418b9..00000000 --- a/Usermode/Libraries/libaxwin2.so_src/windows.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * AxWin Window Manager Interface Library - * By John Hodge (thePowersGang) - * This file is published under the terms of the Acess Licence. See the - * file COPYING for details. - * - * window.c - Window Control - */ -#include "common.h" - -// === TYPES & STRUCTURES === -struct sAxWin_Window -{ - struct sAxWin_Window *Next; - uint32_t WmHandle; - tAxWin_MessageCallback *Callback; -}; - -// === PROTOTYPES === -tAxWin_Window *AxWin_CreateWindow( - int16_t X, int16_t Y, int16_t W, int16_t H, - uint32_t Flags, tAxWin_MessageCallback *Callback - ); - -// === GLOBALS === -//mutex_t glProcessWindows; -tAxWin_Window *gProcessWindows; - -// === CODE === -tAxWin_Window *AxWin_CreateWindow( - int16_t X, int16_t Y, - int16_t W, int16_t H, - uint32_t Flags, tAxWin_MessageCallback *Callback) -{ - tAxWin_Message req; - tAxWin_Message *msg; - tAxWin_Window *win; - - req.ID = MSG_SREQ_NEWWINDOW; - req.Size = 1 + sizeof(struct sAxWin_SReq_NewWindow)/4; - req.SReq_NewWindow.X = X; - req.SReq_NewWindow.Y = Y; - req.SReq_NewWindow.W = W; - req.SReq_NewWindow.H = H; - req.SReq_NewWindow.Flags = Flags; - - AxWin_SendMessage(&msg); - - for(;;) - { - msg = AxWin_WaitForMessage(); - - if(msg.ID == MSG_SRSP_WINDOW) - break; - - AxWin_HandleMessage(msg); - free(msg); - } - - win = malloc(sizeof(tAxWin_Window)); - win->WmHandle = msg->SRsp_Window.Handle; - win->Callback = Callback; - - //mutex_acquire(glProcessWindows); - win->Next = gProcessWindows; - gProcessWindows = win; - //mutex_release(glProcessWindows); - - return 0; -} diff --git a/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/axwin.h b/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/axwin.h index fe116e9d..8d911733 100644 --- a/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/axwin.h +++ b/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/axwin.h @@ -8,6 +8,8 @@ #ifndef _AXWIN3_AXWIN_H_ #define _AXWIN3_AXWIN_H_ +#include // size_t + // === CONSTANTS === // === TYPES === @@ -15,6 +17,7 @@ typedef struct sAxWin3_Window *tHWND; typedef unsigned int tAxWin3_Colour; // TODO: Actual 32-bit typedef void (*tAxWin3_MessageCallback)(int SourceTID, int Length); +typedef void (*tAxWin3_HotkeyCallback)(void); typedef int (*tAxWin3_WindowMessageHandler)(tHWND Window, int Message, int Length, void *Data); @@ -49,9 +52,11 @@ extern tHWND AxWin3_CreateWindow( * \param Window Handle to a window to destroy */ extern void AxWin3_DestroyWindow(tHWND Window); +extern int AxWin3_RegisterAction(tHWND Window, const char *Action, tAxWin3_HotkeyCallback cb); // --- Core window management functions extern void AxWin3_SendMessage(tHWND Window, tHWND Dest, int Message, int Length, void *Data); +extern void *AxWin3_WaitMessage(tHWND Window, int MessageID, size_t *Length); extern void AxWin3_SetWindowTitle(tHWND Window, const char *Title); extern void AxWin3_FocusWindow(tHWND Window); extern void AxWin3_ShowWindow(tHWND Window, int bShow); diff --git a/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/keysyms.h b/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/keysyms.h new file mode 120000 index 00000000..93c2064e --- /dev/null +++ b/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/keysyms.h @@ -0,0 +1 @@ +../../../../../KernelLand/Kernel/include/keysyms.h \ No newline at end of file diff --git a/Usermode/Libraries/libc.so_src/arch/armv6.S b/Usermode/Libraries/libc.so_src/arch/armv6.S new file mode 100644 index 00000000..be4887e8 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/arch/armv6.S @@ -0,0 +1,24 @@ +@ +@ Acess2 C Library +@ - By John Hodge (thePowersGang) +@ +@ arch/armv6.S +@ - ARMv6 specific code +.globl setjmp +setjmp: + @ RO: Buffer + stm r0, {r0-r14} + eor r0, r0 + mov pc, lr + +.globl longjmp +longjmp: + @ R0: Buffer + @ R1: Value + add r0, #8 + ldm r0, {r2-r14} + mov r0, r1 + tst r0, r0 + addeq r0, #1 + mov pc, lr @ Will return to after setjmp + diff --git a/Usermode/Libraries/libc.so_src/heap.c b/Usermode/Libraries/libc.so_src/heap.c index 4fcc8bed..779b0048 100644 --- a/Usermode/Libraries/libc.so_src/heap.c +++ b/Usermode/Libraries/libc.so_src/heap.c @@ -7,6 +7,12 @@ heap.c - Heap Manager #include #include "lib.h" +#if 0 +# define DEBUGS(s...) _SysDebug(s) +#else +# define DEBUGS(s...) do{}while(0) +#endif + // === Constants === #define MAGIC 0xACE55051 //AcessOS1 #define MAGIC_FREE (~MAGIC) @@ -19,6 +25,7 @@ typedef unsigned int Uint; typedef struct { uint32_t magic; size_t size; + char data[]; } heap_head; typedef struct { heap_head *header; @@ -38,6 +45,7 @@ EXPORT void *sbrk(int increment); LOCAL void *extendHeap(int bytes); static void *FindHeapBase(); LOCAL uint brk(uintptr_t newpos); +LOCAL void Heap_Dump(void); //Code @@ -53,7 +61,7 @@ EXPORT void *malloc(size_t bytes) size_t closestMatch = 0; void *bestMatchAddr = 0; heap_head *curBlock; - + // _SysDebug("&_heap_start = %p, _heap_start = %p", &_heap_start, _heap_start); // Initialise Heap if(_heap_start == NULL) @@ -84,6 +92,7 @@ EXPORT void *malloc(size_t bytes) else if(curBlock->magic != MAGIC) { //Corrupt Heap + Heap_Dump(); _SysDebug("malloc: Corrupt Heap\n"); return NULL; } @@ -109,9 +118,12 @@ EXPORT void *malloc(size_t bytes) return NULL; } curBlock->magic = MAGIC; - return (void*)((uintptr_t)curBlock + sizeof(heap_head)); + DEBUGS("malloc(0x%x) = %p (extend) 0x%x", bytes, curBlock->data, bestSize); + return curBlock->data; } + heap_head *besthead = (void*)bestMatchAddr; + //Split Block? if(closestMatch - bestSize > BLOCK_SIZE) { heap_foot *foot; @@ -129,13 +141,15 @@ EXPORT void *malloc(size_t bytes) foot = (heap_foot*)(bestMatchAddr + closestMatch - sizeof(heap_foot)); foot->header = curBlock; - ((heap_head*)bestMatchAddr)->magic = MAGIC; //mark as used - return (void*)(bestMatchAddr + sizeof(heap_head)); + besthead->magic = MAGIC; //mark as used + DEBUGS("malloc(0x%x) = %p (split) 0x%x", bytes, besthead->data, bestSize); + return besthead->data; } //Don't Split the block - ((heap_head*)bestMatchAddr)->magic = MAGIC; - return (void*)(bestMatchAddr+sizeof(heap_head)); + besthead->magic = MAGIC; + DEBUGS("malloc(0x%x) = %p (reuse) 0x%x", bytes, besthead->data, besthead->size); + return besthead->data; } /** @@ -168,6 +182,7 @@ EXPORT void free(void *mem) return; head->magic = MAGIC_FREE; + DEBUGS("free(%p) : 0x%x bytes", mem, head->size); //Unify Right if((intptr_t)head + head->size < (intptr_t)_heap_end) @@ -429,3 +444,25 @@ LOCAL uint brk(uintptr_t newpos) return ret; // Return old curpos } + +void Heap_Dump(void) +{ + heap_head *cur = _heap_start; + while( cur < _heap_end ) + { + switch( cur->magic ) + { + case MAGIC: + _SysDebug("Used block %p[0x%x] - ptr=%p", cur, cur->size, cur->data); + break; + case MAGIC_FREE: + _SysDebug("Free block %p[0x%x] - ptr=%p", cur, cur->size, cur->data); + break; + default: + _SysDebug("Block %p bad magic (0x%x)", cur, cur->magic); + return ; + } + cur = (void*)( (char*)cur + cur->size ); + } +} + diff --git a/Usermode/Libraries/libc.so_src/include_exp/stdlib.h b/Usermode/Libraries/libc.so_src/include_exp/stdlib.h index 0e6d9e03..8acfb8bc 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/stdlib.h +++ b/Usermode/Libraries/libc.so_src/include_exp/stdlib.h @@ -20,10 +20,15 @@ /* --- StdLib --- */ extern void _exit(int code) __attribute__((noreturn)); /* NOTE: Also defined in acess/sys.h */ +extern long long strtoll(const char *ptr, char **end, int base); +extern long strtol(const char *ptr, char **end, int base); extern int atoi(const char *ptr); extern void exit(int status) __attribute__((noreturn)); extern void atexit(void (*__func)(void)); extern void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); +extern int abs(int j); +extern long int labs(long int j); +extern long long int llabs(long long int j); /* --- Environment --- */ extern char *getenv(const char *name); diff --git a/Usermode/Libraries/libc.so_src/stdlib.c b/Usermode/Libraries/libc.so_src/stdlib.c index ddd1234a..c91106c4 100644 --- a/Usermode/Libraries/libc.so_src/stdlib.c +++ b/Usermode/Libraries/libc.so_src/stdlib.c @@ -2,12 +2,12 @@ * AcessOS Basic C Library * stdlib.c */ -/** - * \todo Move half of these to stdio - */ #include #include #include +#include +#include +#include #include "lib.h" #define _stdout 1 @@ -71,70 +71,96 @@ EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void } } -/** - * \fn EXPORT int atoi(const char *str) - * \brief Convert a string to an integer - */ -EXPORT int atoi(const char *str) +EXPORT long long strtoll(const char *str, char **end, int base) { int neg = 0; - int ret = 0; - - // NULL Check - if(!str) return 0; + long long ret = 0; - while(*str == ' ' || *str == '\t') str++; + if( !str || base < 0 || base > 36 || base == 1 ) { + if(end) + *end = (char*)str; + errno = EINVAL; + return 0; + } + + while( isspace(*str) ) + str++; - // Check for negative - if(*str == '-') { - neg = 1; + // Check for negative (or positive) sign + if(*str == '-' || *str == '+') { + neg = (*str == '-'); str++; } - if(*str == '0') { + if( base == 0 || base == 16 ) { + if( *str == '0' && str[1] == 'x' ) { + str += 2; + base = 16; + } + } + + if( base == 0 && *str == '0' ) { str ++; - if(*str == 'x') { - str++; - // Hex - while( ('0' <= *str && *str <= '9') - || ('A' <= *str && *str <= 'F' ) - || ('a' <= *str && *str <= 'f' ) - ) - { - ret *= 16; - if(*str <= '9') { - ret += *str - '0'; - } else if (*str <= 'F') { - ret += *str - 'A' + 10; - } else { - ret += *str - 'a' + 10; - } - str++; - } - } else { - // Octal - while( '0' <= *str && *str <= '7' ) - { - ret *= 8; - ret += *str - '0'; - str++; - } + base = 8; + } + + if( base == 0 ) + base = 10; + + while( *str ) + { + int next = -1; + if( base <= 10 ) { + if( '0' <= *str && *str <= '0'+base-1 ) + next = *str - '0'; } - } else { - // Decimal - while( '0' <= *str && *str <= '9' ) - { - ret *= 10; - ret += *str - '0'; - str++; + else { + if( '0' <= *str && *str <= '9' ) + next = *str - '0'; + if( 'A' <= *str && *str <= 'A'+base-10-1 ) + next = *str - 'A'; + if( 'a' <= *str && *str <= 'a'+base-10-1 ) + next = *str - 'a'; } + if( next < 0 ) + break; + ret *= base; + ret += next; + str ++; } - - // Negate if needed - if(neg) ret = -ret; + + if( neg ) + ret = -ret; + + if(end) + *end = (char*)str; return ret; } +EXPORT long strtol(const char *str, char **end, int base) +{ + long long tmp = strtoll(str, end, base); + if( tmp > LONG_MAX || tmp < LONG_MIN ) { + errno = ERANGE; + return (tmp > LONG_MAX) ? LONG_MAX : LONG_MIN; + } + return tmp; +} + +/** + * \fn EXPORT int atoi(const char *str) + * \brief Convert a string to an integer + */ +EXPORT int atoi(const char *str) +{ + long long tmp = strtoll(str, NULL, 0); + if( tmp > INT_MAX || tmp < INT_MIN ) { + errno = ERANGE; + return (tmp > INT_MAX) ? INT_MAX : INT_MIN; + } + return tmp; +} + int abs(int j) { return j < 0 ? -j : j; } long int labs(long int j) { return j < 0 ? -j : j; } diff --git a/Usermode/Libraries/libc.so_src/string.c b/Usermode/Libraries/libc.so_src/string.c index e9e15741..3cadee90 100644 --- a/Usermode/Libraries/libc.so_src/string.c +++ b/Usermode/Libraries/libc.so_src/string.c @@ -273,10 +273,11 @@ EXPORT void *memmove(void *dest, const void *src, size_t count) char *sp = (char *)src; char *dp = (char *)dest; // Check if the areas overlap - if( (intptr_t)dest > (intptr_t)src && (intptr_t)dest < (intptr_t)src+count ) - for(;count--;) dp[count] = sp[count]; + if( (intptr_t)src < (intptr_t)dest && (intptr_t)dest < (intptr_t)src+count ) + for(;count--;) + dp[count] = sp[count]; else - for(;count--;) *dp++ = *sp++; + memcpy(dest, src, count); return dest; }