diff --git a/Makefile b/Makefile index eab66e0..f572f5b 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ MAKEFLAGS += --no-print-directory #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lz -liosuhax +LIBS := -lz -liosuhax -lgd #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/src/dynamic_libs/gx2_functions.h b/src/dynamic_libs/gx2_functions.h index 0affa11..2ecf3d2 100644 --- a/src/dynamic_libs/gx2_functions.h +++ b/src/dynamic_libs/gx2_functions.h @@ -29,6 +29,7 @@ extern "C" { #endif #include "gx2_types.h" +#include "../common/fs_defs.h" void InitGX2FunctionPointers(void); diff --git a/src/dynamic_libs/socket_functions.h b/src/dynamic_libs/socket_functions.h index 85b12be..03c9071 100644 --- a/src/dynamic_libs/socket_functions.h +++ b/src/dynamic_libs/socket_functions.h @@ -95,4 +95,4 @@ extern int (*inet_aton)(const char *cp, struct in_addr *inp); } #endif -#endif // __SOCKET_FUNCTIONS_H_ +#endif \ No newline at end of file diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 03bcca6..580e794 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -8,247 +8,235 @@ extern void my_PrepareTitle_hook(void); static unsigned int origPrepareTitleInstr = 0; -static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len) -{ - /* - * Setup a DBAT access with cache inhibited to write through and read directly from memory - */ - unsigned int dbatu0, dbatl0, dbatu1, dbatl1; - // save the original DBAT value - asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); - asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); - asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); - asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); +static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len) { + /* + * Setup a DBAT access with cache inhibited to write through and read directly from memory + */ + unsigned int dbatu0, dbatl0, dbatu1, dbatl1; + // save the original DBAT value + asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); + asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); + asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); + asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); - unsigned int target_dbatu0 = 0; - unsigned int target_dbatl0 = 0; - unsigned int target_dbatu1 = 0; - unsigned int target_dbatl1 = 0; + unsigned int target_dbatu0 = 0; + unsigned int target_dbatl0 = 0; + unsigned int target_dbatu1 = 0; + unsigned int target_dbatl1 = 0; - unsigned char *dst_p = (unsigned char*)addr; - unsigned char *src_p = (unsigned char*)src; + unsigned char *dst_p = (unsigned char *) addr; + unsigned char *src_p = (unsigned char *) src; - // we only need DBAT modification for addresses out of our own DBAT range - // as our own DBAT is available everywhere for user and supervisor - // since our own DBAT is on DBAT5 position we don't collide here - if(addr < 0x00800000 || addr >= 0x01000000) - { - target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F; - target_dbatl0 = (addr & 0xFFF00000) | 0x32; - asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); - asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); - dst_p = (unsigned char*)((addr & 0xFFFFFF) | 0xC0000000); - } - if(src < 0x00800000 || src >= 0x01000000) - { - target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F; - target_dbatl1 = (src & 0xFFF00000) | 0x32; + // we only need DBAT modification for addresses out of our own DBAT range + // as our own DBAT is available everywhere for user and supervisor + // since our own DBAT is on DBAT5 position we don't collide here + if (addr < 0x00800000 || addr >= 0x01000000) { + target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F; + target_dbatl0 = (addr & 0xFFF00000) | 0x32; + asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); + dst_p = (unsigned char *) ((addr & 0xFFFFFF) | 0xC0000000); + } + if (src < 0x00800000 || src >= 0x01000000) { + target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F; + target_dbatl1 = (src & 0xFFF00000) | 0x32; - asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); - asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); - src_p = (unsigned char*)((src & 0xFFFFFF) | 0xB0000000); - } + asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); + src_p = (unsigned char *) ((src & 0xFFFFFF) | 0xB0000000); + } - asm volatile("eieio; isync"); + asm volatile("eieio; isync"); - unsigned int i; - for(i = 0; i < len; i++) - { - // if we are on the edge to next chunk - if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000))) - { - target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F; - target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32; - dst_p = (unsigned char*)(((addr + i) & 0xFFFFFF) | 0xC0000000); + unsigned int i; + for (i = 0; i < len; i++) { + // if we are on the edge to next chunk + if ((target_dbatu0 != 0) && (((unsigned int) dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000))) { + target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F; + target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32; + dst_p = (unsigned char *) (((addr + i) & 0xFFFFFF) | 0xC0000000); - asm volatile("eieio; isync"); - asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); - asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); - asm volatile("eieio; isync"); - } - if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000))) - { - target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F; - target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32; - src_p = (unsigned char*)(((src + i) & 0xFFFFFF) | 0xB0000000); + asm volatile("eieio; isync"); + asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); + asm volatile("eieio; isync"); + } + if ((target_dbatu1 != 0) && (((unsigned int) src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000))) { + target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F; + target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32; + src_p = (unsigned char *) (((src + i) & 0xFFFFFF) | 0xB0000000); - asm volatile("eieio; isync"); - asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); - asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); - asm volatile("eieio; isync"); - } + asm volatile("eieio; isync"); + asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); + asm volatile("eieio; isync"); + } - *dst_p = *src_p; + *dst_p = *src_p; - ++dst_p; - ++src_p; - } + ++dst_p; + ++src_p; + } - /* - * Restore original DBAT value + /* + * Restore original DBAT value */ - asm volatile("eieio; isync"); - asm volatile("mtdbatu 0, %0" : : "r" (dbatu0)); - asm volatile("mtdbatl 0, %0" : : "r" (dbatl0)); - asm volatile("mtdbatu 1, %0" : : "r" (dbatu1)); - asm volatile("mtdbatl 1, %0" : : "r" (dbatl1)); - asm volatile("eieio; isync"); + asm volatile("eieio; isync"); + asm volatile("mtdbatu 0, %0" : : "r" (dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (dbatl0)); + asm volatile("mtdbatu 1, %0" : : "r" (dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (dbatl1)); + asm volatile("eieio; isync"); } -static void KernelReadDBATs(bat_table_t * table) -{ - u32 i = 0; +static void KernelReadDBATs(bat_table_t *table) { + u32 i = 0; - asm volatile("eieio; isync"); + asm volatile("eieio; isync"); - asm volatile("mfspr %0, 536" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 537" : "=r" (table->bat[i].l)); - i++; - asm volatile("mfspr %0, 538" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 539" : "=r" (table->bat[i].l)); - i++; - asm volatile("mfspr %0, 540" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 541" : "=r" (table->bat[i].l)); - i++; - asm volatile("mfspr %0, 542" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 543" : "=r" (table->bat[i].l)); - i++; + asm volatile("mfspr %0, 536" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 537" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 538" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 539" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 540" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 541" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 542" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 543" : "=r" (table->bat[i].l)); + i++; - asm volatile("mfspr %0, 568" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 569" : "=r" (table->bat[i].l)); - i++; - asm volatile("mfspr %0, 570" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 571" : "=r" (table->bat[i].l)); - i++; - asm volatile("mfspr %0, 572" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 573" : "=r" (table->bat[i].l)); - i++; - asm volatile("mfspr %0, 574" : "=r" (table->bat[i].h)); - asm volatile("mfspr %0, 575" : "=r" (table->bat[i].l)); + asm volatile("mfspr %0, 568" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 569" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 570" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 571" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 572" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 573" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 574" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 575" : "=r" (table->bat[i].l)); } -static void KernelWriteDBATs(bat_table_t * table) -{ - u32 i = 0; +static void KernelWriteDBATs(bat_table_t *table) { + u32 i = 0; - asm volatile("eieio; isync"); + asm volatile("eieio; isync"); - asm volatile("mtspr 536, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 537, %0" : : "r" (table->bat[i].l)); - i++; - asm volatile("mtspr 538, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 539, %0" : : "r" (table->bat[i].l)); - i++; - asm volatile("mtspr 540, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 541, %0" : : "r" (table->bat[i].l)); - i++; - asm volatile("mtspr 542, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 543, %0" : : "r" (table->bat[i].l)); - i++; + asm volatile("mtspr 536, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 537, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 538, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 539, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 540, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 541, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 542, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 543, %0" : : "r" (table->bat[i].l)); + i++; - asm volatile("mtspr 568, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 569, %0" : : "r" (table->bat[i].l)); - i++; - asm volatile("mtspr 570, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 571, %0" : : "r" (table->bat[i].l)); - i++; - asm volatile("mtspr 572, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 573, %0" : : "r" (table->bat[i].l)); - i++; - asm volatile("mtspr 574, %0" : : "r" (table->bat[i].h)); - asm volatile("mtspr 575, %0" : : "r" (table->bat[i].l)); + asm volatile("mtspr 568, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 569, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 570, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 571, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 572, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 573, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 574, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 575, %0" : : "r" (table->bat[i].l)); - asm volatile("eieio; isync"); + asm volatile("eieio; isync"); } /* Read a 32-bit word with kernel permissions */ -uint32_t __attribute__ ((noinline)) kern_read(const void *addr) -{ +uint32_t __attribute__ ((noinline)) kern_read(const void *addr) { uint32_t result; asm volatile ( - "li 3,1\n" - "li 4,0\n" - "li 5,0\n" - "li 6,0\n" - "li 7,0\n" - "lis 8,1\n" - "mr 9,%1\n" - "li 0,0x3400\n" - "mr %0,1\n" - "sc\n" - "nop\n" - "mr 1,%0\n" - "mr %0,3\n" - : "=r"(result) - : "b"(addr) - : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", - "11", "12" + "li 3,1\n" + "li 4,0\n" + "li 5,0\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%1\n" + "li 0,0x3400\n" + "mr %0,1\n" + "sc\n" + "nop\n" + "mr 1,%0\n" + "mr %0,3\n" + : "=r"(result) + : "b"(addr) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" ); return result; } /* Write a 32-bit word with kernel permissions */ -void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) -{ +void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) { asm volatile ( - "li 3,1\n" - "li 4,0\n" - "mr 5,%1\n" - "li 6,0\n" - "li 7,0\n" - "lis 8,1\n" - "mr 9,%0\n" - "mr %1,1\n" - "li 0,0x3500\n" - "sc\n" - "nop\n" - "mr 1,%1\n" - : - : "r"(addr), "r"(value) - : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", - "11", "12" - ); + "li 3,1\n" + "li 4,0\n" + "mr 5,%1\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%0\n" + "mr %1,1\n" + "li 0,0x3500\n" + "sc\n" + "nop\n" + "mr 1,%1\n" + : + : "r"(addr), "r"(value) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); } -void KernelSetupSyscalls(void) -{ - //! assign 1 so that this variable gets into the retained .data section - static uint8_t ucSyscallsSetupRequired = 1; - if(!ucSyscallsSetupRequired) - return; +void KernelSetupSyscalls(void) { + //! assign 1 so that this variable gets into the retained .data section + static uint8_t ucSyscallsSetupRequired = 1; + if (!ucSyscallsSetupRequired) + return; - ucSyscallsSetupRequired = 0; + ucSyscallsSetupRequired = 0; - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x36 * 4)), (unsigned int)KernelReadDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x36 * 4)), (unsigned int)KernelReadDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x36 * 4)), (unsigned int)KernelReadDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x36 * 4)), (unsigned int)KernelReadDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl1 + (0x36 * 4)), (unsigned int) KernelReadDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl2 + (0x36 * 4)), (unsigned int) KernelReadDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl3 + (0x36 * 4)), (unsigned int) KernelReadDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl4 + (0x36 * 4)), (unsigned int) KernelReadDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl5 + (0x36 * 4)), (unsigned int) KernelReadDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl1 + (0x37 * 4)), (unsigned int) KernelWriteDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl2 + (0x37 * 4)), (unsigned int) KernelWriteDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl3 + (0x37 * 4)), (unsigned int) KernelWriteDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl4 + (0x37 * 4)), (unsigned int) KernelWriteDBATs); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl5 + (0x37 * 4)), (unsigned int) KernelWriteDBATs); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int)KernelCopyData); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int)KernelCopyData); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int)KernelCopyData); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int)KernelCopyData); - kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int) KernelCopyData); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int) KernelCopyData); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int) KernelCopyData); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int) KernelCopyData); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int) KernelCopyData); - //! write our hook to the - u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003; - DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook)); + //! write our hook to the + u32 addr_my_PrepareTitle_hook = ((u32) my_PrepareTitle_hook) | 0x48000003; + DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook)); - SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4); - SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4); + SC0x25_KernelCopyData((u32) &origPrepareTitleInstr, (u32) addr_PrepareTitle_hook, 4); + SC0x25_KernelCopyData((u32) addr_PrepareTitle_hook, (u32) OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4); } -void KernelRestoreInstructions(void) -{ - if(origPrepareTitleInstr != 0) - SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&origPrepareTitleInstr, 4); +void KernelRestoreInstructions(void) { + if (origPrepareTitleInstr != 0) + SC0x25_KernelCopyData((u32) addr_PrepareTitle_hook, (u32) &origPrepareTitleInstr, 4); } diff --git a/src/kernel/syscalls.h b/src/kernel/syscalls.h index 283aa0d..298d599 100644 --- a/src/kernel/syscalls.h +++ b/src/kernel/syscalls.h @@ -6,7 +6,6 @@ extern "C" { #endif #include -#include "common/kernel_defs.h" #include "../common/kernel_defs.h" void KernelSetupSyscalls(void); diff --git a/src/main.c b/src/main.c index 158ed0d..f25f6b5 100644 --- a/src/main.c +++ b/src/main.c @@ -10,21 +10,28 @@ #include "dynamic_libs/sys_functions.h" #include "dynamic_libs/vpad_functions.h" #include "dynamic_libs/socket_functions.h" -#include "patcher/function_hooks.h" #include "kernel/kernel_functions.h" #include "system/memory.h" #include "common/common.h" #include "main.h" #include "code_handler.h" +#include "utils/logger.h" +#include "utils/function_patcher.h" +#include "patcher/function_patcher_gx2.h" bool isCodeHandlerInstalled; #define PRINT_TEXT2(x, y, ...) { snprintf(messageBuffer, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, messageBuffer); OSScreenPutFontEx(1, x, y, messageBuffer); } typedef enum { - EXIT = 0x0, TCP_GECKO = 0x1 + EXIT, + TCP_GECKO } LaunchMethod; +void applyFunctionPatches() { + patchIndividualMethodHooks(method_hooks_gx2, method_hooks_size_gx2, method_calls_gx2); +} + /* Entry point */ int Menu_Main(void) { //!******************************************************************* @@ -37,6 +44,10 @@ int Menu_Main(void) { InitVPadFunctionPointers(); InitSysFunctionPointers(); + log_init(COMPUTER_IP_ADDRESS); + log_print("Patching functions\n"); + applyFunctionPatches(); + if (strcasecmp("men.rpx", cosAppXmlInfoStruct.rpx_name) == 0) { return EXIT_RELAUNCH_ON_LOAD; } else if (strlen(cosAppXmlInfoStruct.rpx_name) > 0 && @@ -73,7 +84,7 @@ int Menu_Main(void) { ); SetupKernelCallback(); - PatchMethodHooks(); + // PatchMethodHooks(); memoryInitialize(); @@ -143,7 +154,8 @@ int Menu_Main(void) { } // Button pressed ? - update_screen = (pressedButtons & (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN)) ? 1 : 0; + update_screen = (pressedButtons & (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN)) + ? 1 : 0; usleep(20 * 1000); } @@ -156,7 +168,7 @@ int Menu_Main(void) { memoryRelease(); if (launchMethod == EXIT) { - RestoreInstructions(); + // RestoreInstructions(); return EXIT_SUCCESS; } else { SYSLaunchMenu(); diff --git a/src/main.h b/src/main.h index 361e1a6..cc72010 100644 --- a/src/main.h +++ b/src/main.h @@ -9,8 +9,6 @@ extern "C" { #endif -#define COMPUTER_IP_ADDRESS "192.168.2.103" - //! C wrapper for our C++ functions int Menu_Main(void); diff --git a/src/patcher/fs_logger.c b/src/patcher/fs_logger.c index 163ddf5..20e9e37 100644 --- a/src/patcher/fs_logger.c +++ b/src/patcher/fs_logger.c @@ -2,7 +2,6 @@ #include "common/common.h" #include "../dynamic_libs/os_functions.h" #include "../dynamic_libs/socket_functions.h" -#include "function_hooks.h" #include "fs_logger.h" #include "utils/utils.h" diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c deleted file mode 100644 index 469801e..0000000 --- a/src/patcher/function_hooks.c +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include -#include -#include "../common/common.h" -#include "../dynamic_libs/os_functions.h" -#include "../kernel/kernel_functions.h" -#include "function_hooks.h" -#include "../dynamic_libs/gx2_types.h" - -#define LIB_CODE_RW_BASE_OFFSET 0xC1000000 -#define CODE_RW_BASE_OFFSET 0x00000000 - -#define DECL(res, name, ...) \ - res (* real_ ## name)(__VA_ARGS__); \ - res my_ ## name(__VA_ARGS__) - -/* ***************************************************************************** - * Creates function pointer array - * ****************************************************************************/ -// #define MAKE_MAGIC(x, lib) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x } - -#define MAKE_MAGIC(x, lib, functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x,0,0,functionType,0} - -DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, - s32 scan_target) { - // TODO Does not execute - GX2Surface surface = colorBuffer->surface; - u32 image_size = surface.image_size; - char buffer[100] = {0}; - __os_snprintf(buffer, 100, "Image size: %i", image_size); - OSFatal(buffer); - - real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); -} - -DECL(int, FSInit, void) { - return real_FSInit(); -} - -DECL(int, socket_lib_finish, void) { - return 0; -} - -static const struct hooks_magic_t { - const unsigned int replaceAddr; - const unsigned int replaceCall; - const unsigned int library; - const char functionName[50]; - unsigned int realAddr; - unsigned int restoreInstruction; - unsigned char functionType; - unsigned char alreadyPatched; -} method_hooks[] = { - MAKE_MAGIC(FSInit, LIB_CORE_INIT, STATIC_FUNCTION), - MAKE_MAGIC(socket_lib_finish, LIB_CORE_INIT, STATIC_FUNCTION), - MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, DYNAMIC_FUNCTION), -}; - -//! buffer to store our 2 instructions needed for our replacements -//! the code will be placed in the address of that buffer - CODE_RW_BASE_OFFSET -//! avoid this buffer to be placed in BSS and reset on start up -volatile unsigned int fs_method_calls[sizeof(method_hooks) / sizeof(struct hooks_magic_t) * 2]; - -void PatchMethodHooks(void) { - restore_instructions_t *restore = RESTORE_INSTR_ADDR; - //! check if it is already patched - if (restore->magic == RESTORE_INSTR_MAGIC) - return; - - restore->magic = RESTORE_INSTR_MAGIC; - restore->instr_count = 0; - - bat_table_t table; - KernelSetDBATs(&table); - - /* Patch branches to it. */ - volatile unsigned int *space = &fs_method_calls[0]; - - int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t); - - for (int i = 0; i < method_hooks_count; i++) { - unsigned int repl_addr = method_hooks[i].replaceAddr; - unsigned int call_addr = method_hooks[i].replaceCall; - - unsigned int real_addr = 0; - - if (strcmp(method_hooks[i].functionName, "OSDynLoad_Acquire") == 0) { - memcpy(&real_addr, &OSDynLoad_Acquire, 4); - } else { - OSDynLoad_FindExport(coreinit_handle, 0, method_hooks[i].functionName, &real_addr); - } - - // fill the restore instruction section - restore->data[restore->instr_count].addr = real_addr; - restore->data[restore->instr_count].instr = *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + real_addr); - restore->instr_count++; - - // set pointer to the real function - *(volatile unsigned int *) (call_addr) = (unsigned int) (space) - CODE_RW_BASE_OFFSET; - DCFlushRange((void *) (call_addr), 4); - - // fill the instruction of the real function - *space = *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + real_addr); - space++; - - // jump to real function skipping the first/replaced instruction - *space = 0x48000002 | ((real_addr + 4) & 0x03fffffc); - space++; - DCFlushRange((void *) (space - 2), 8); - ICInvalidateRange((unsigned char *) (space - 2) - CODE_RW_BASE_OFFSET, 8); - - unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc); - *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + real_addr) = replace_instr; - DCFlushRange((void *) (LIB_CODE_RW_BASE_OFFSET + real_addr), 4); - ICInvalidateRange((void *) (real_addr), 4); - } - - KernelRestoreDBATs(&table); -} - -/* ****************************************************************** */ -/* RESTORE ORIGINAL INSTRUCTIONS */ -/* ****************************************************************** */ -void RestoreInstructions(void) { - bat_table_t table; - KernelSetDBATs(&table); - - restore_instructions_t *restore = RESTORE_INSTR_ADDR; - if (restore->magic == RESTORE_INSTR_MAGIC) { - for (unsigned int i = 0; i < restore->instr_count; i++) { - *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + restore->data[i].addr) = restore->data[i].instr; - DCFlushRange((void *) (LIB_CODE_RW_BASE_OFFSET + restore->data[i].addr), (u32) 4); - ICInvalidateRange((void *) restore->data[i].addr, (u32) 4); - } - } - restore->magic = 0; - restore->instr_count = 0; - - KernelRestoreDBATs(&table); - KernelRestoreInstructions(); -} \ No newline at end of file diff --git a/src/patcher/function_hooks.h b/src/patcher/function_hooks.h deleted file mode 100644 index 02fddfd..0000000 --- a/src/patcher/function_hooks.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _FUNCTION_HOOKS_H_ -#define _FUNCTION_HOOKS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void PatchMethodHooks(void); -void RestoreInstructions(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _FS_H */ diff --git a/src/patcher/function_patcher_gx2.c b/src/patcher/function_patcher_gx2.c new file mode 100644 index 0000000..8674bdc --- /dev/null +++ b/src/patcher/function_patcher_gx2.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell, BullyWiiPlaza + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include // malloc()/free() +#include // image library +#include "../utils/function_patcher.h" +#include "../utils/logger.h" +#include "texture.h" +#include + +static volatile int executionCounter = 0; + +declareFunctionHook(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 + scan_target) { + if (executionCounter > 120) { + GX2Surface surface = colorBuffer->surface; + /*s32 format = surface.format; + + gdImagePtr gdImagePtr = 0; + bool no_convert; + u8 *image_data = NULL; + int img_size = 0; + if (format == 0x1A) { + UnormR8G8B8A82Yuv420p(&image_data, surface.image_data, &img_size, surface.width, surface.height, + surface.pitch); + } else if (format == 0x19) { + no_convert = true; + UnormR8G8B8A8TogdImage(&gdImagePtr, surface.image_data, surface.width, surface.height, surface.pitch); + } else { + no_convert = true; + } + + u32 imd_size = 0; + void *data = gdImageJpegPtr(gdImagePtr, &imd_size, 95); + if (data) { + JpegData jpeg; + jpeg.img_size = imd_size; + jpeg.img_data = data; + jpeg.img_id = 0; + }*/ + + log_printf("GX2CopyColorBufferToScanBuffer {surface width:%d, height:%d, image size:%d, image data:%x}\n", + surface.width, surface.height, surface.image_size, surface.image_data); + + executionCounter = 0; + } + + executionCounter++; + + real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); +} + +FunctionHook method_hooks_gx2[] __attribute__((section(".data"))) = { + makeFunctionHook(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION) +}; + +u32 method_hooks_size_gx2 __attribute__((section(".data"))) = sizeof(method_hooks_gx2) / sizeof(FunctionHook); + +volatile unsigned int method_calls_gx2[sizeof(method_hooks_gx2) / sizeof(FunctionHook) * + FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data"))); \ No newline at end of file diff --git a/src/patcher/function_patcher_gx2.h b/src/patcher/function_patcher_gx2.h new file mode 100644 index 0000000..86f6893 --- /dev/null +++ b/src/patcher/function_patcher_gx2.h @@ -0,0 +1,34 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef FUNCTION_PATCHER_EXAMPLE_GX2_FUNCTION_PATCHER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../utils/function_patcher.h" + +extern FunctionHook method_hooks_gx2[]; +extern u32 method_hooks_size_gx2; +extern volatile unsigned int method_calls_gx2[]; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/patcher/texture.h b/src/patcher/texture.h new file mode 100644 index 0000000..7724dc4 --- /dev/null +++ b/src/patcher/texture.h @@ -0,0 +1,103 @@ +#pragma once + +#include "../common/fs_defs.h" +#include "../utils/logger.h" +#include "../dynamic_libs/os_functions.h" +#include + +typedef struct +{ + u32 img_size; + u32 img_id; + void * img_data; +} JpegData; + +typedef struct _R8G8B8A8_COLOR { + u8 R, G, B, A; +} R8G8B8A8_COLOR; + +void UnormR8G8B8A8TogdImage(gdImagePtr *gdImgTmp, void *image_data, u32 width, u32 rows, u32 pitch) { + *gdImgTmp = gdImageCreateTrueColor(width / 2, rows / 2); + + R8G8B8A8_COLOR *buffer = (R8G8B8A8_COLOR *) image_data; + R8G8B8A8_COLOR val; + for (u32 row = 0; row < rows; ++row) { + for (u32 x = 0; x < width; ++x) { + val = buffer[row * pitch + x]; + gdImageSetPixel(*gdImgTmp, x / 2, row / 2, gdTrueColor(val.R, val.G, val.B)); + ++x; + } + ++row; + } +} + +void UnormR8G8B8A82Yuv420p(u8 **destination_, void *image_data, int *dest_img_size, u32 width, u32 height, u32 pitch) { + u32 image_size = width * height; + u32 upos = image_size; + u32 vpos = upos + upos / 4; + *dest_img_size = (vpos + upos / 4); + if (*destination_) { + free(destination_); + } + *destination_ = (u8 *) malloc(sizeof(u8) * *dest_img_size); + u8 *destination = *destination_; + if (!destination) { + *dest_img_size = 0; + return; + } + log_printf("allocated %d \n", *dest_img_size); + + R8G8B8A8_COLOR *buffer = (R8G8B8A8_COLOR *) image_data; + + u32 i = 0; + + for (u32 line = 0; line < height; ++line) { + if (!(line % 2)) { + for (u32 x = 0; x < width; x += 2) { + u8 r = buffer[line * pitch + x].R; + u8 g = buffer[line * pitch + x].G; + u8 b = buffer[line * pitch + x].B; + + destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16; + + destination[upos++] = ((-38 * r + -74 * g + 112 * b) >> 8) + 128; + destination[vpos++] = ((112 * r + -94 * g + -18 * b) >> 8) + 128; + + r = buffer[line * pitch + x].R; + g = buffer[line * pitch + x].G; + b = buffer[line * pitch + x].B; + + destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16; + } + } else { + for (u32 x = 0; x < width; x += 1) { + u8 r = buffer[line * pitch + x].R; + u8 g = buffer[line * pitch + x].G; + u8 b = buffer[line * pitch + x].B; + + destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16; + } + } + } + sleep(1); + log_printf("done %d \n", *dest_img_size); +} + +void UnormR10G10B10A2TogdImage(gdImagePtr *gdImgTmp, void *image_data, u32 width, u32 rows, u32 pitch) { + u32 *buffer = (u32 *) image_data; + u32 val = 0; + for (u32 row = 0; row < rows; ++row) { + for (u32 x = 0; x < width; ++x) { + /* + R ((test >> 24) & 0xFF)) + G ((test >> 14) & 0xFF)) + B ((test >> 4) & 0xFF)) + alpha (test & 0x3); + */ + val = buffer[row * pitch + x]; + gdImageSetPixel(*gdImgTmp, x, row, gdTrueColor(((val >> 24) & 0xFF), + ((val >> 14) & 0xFF), + ((val >> 4) & 0xFF))); + } + } +} \ No newline at end of file diff --git a/src/pygecko.c b/src/pygecko.c index cbed7b7..a0e9854 100644 --- a/src/pygecko.c +++ b/src/pygecko.c @@ -78,7 +78,7 @@ struct pygecko_bss_t { #define EWOULDBLOCK 6 #define DATA_BUFFER_SIZE 0x5000 // #define WRITE_SCREEN_MESSAGE_BUFFER_SIZE 100 -#define SERVER_VERSION "05/24/2017" +#define SERVER_VERSION "06/02/2017" #define ONLY_ZEROS_READ 0xB0 #define NON_ZEROS_READ 0xBD @@ -378,7 +378,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { } case COMMAND_READ_MEMORY_KERNEL: { const unsigned char *startingAddress, *endingAddress, *useKernRead; - ret = recvwait(bss, clientfd, buffer, 3 * 4); + ret = recvwait(bss, clientfd, buffer, 3 * sizeof(int)); CHECK_ERROR(ret < 0) startingAddress = ((const unsigned char **) buffer)[0]; endingAddress = ((const unsigned char **) buffer)[1]; @@ -395,7 +395,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { // Figure out if all bytes are zero to possibly avoid sending them int rangeIterationIndex = 0; for (; rangeIterationIndex < length; rangeIterationIndex++) { - int character = useKernRead ? kern_read(startingAddress + rangeIterationIndex) + int character = useKernRead ? readKernelMemory(startingAddress + rangeIterationIndex) : startingAddress[rangeIterationIndex]; if (character != 0) { break; @@ -407,11 +407,12 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { ret = sendByte(bss, clientfd, ONLY_ZEROS_READ); CHECK_ERROR(ret < 0) } else { + // Send the real bytes now buffer[0] = NON_ZEROS_READ; if (useKernRead) { - for (int offset = 0; offset < length; offset += 4) { - *((int *) (buffer + 1) + offset / 4) = kern_read(startingAddress + offset); + for (int offset = 0; offset < length; offset += sizeof(int)) { + *((int *) (buffer + 1) + offset / sizeof(int)) = readKernelMemory(startingAddress + offset); } } else { memcpy(buffer + 1, startingAddress, length); @@ -601,26 +602,26 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { } case COMMAND_KERNEL_WRITE: { void *ptr, *value; - ret = recvwait(bss, clientfd, buffer, 8); + ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2); CHECK_ERROR(ret < 0) ptr = ((void **) buffer)[0]; value = ((void **) buffer)[1]; - kern_write(ptr, (uint32_t) value); + writeKernelMemory(ptr, (uint32_t) value); break; } case COMMAND_KERNEL_READ: { void *ptr, *value; - ret = recvwait(bss, clientfd, buffer, 4); + ret = recvwait(bss, clientfd, buffer, sizeof(int)); CHECK_ERROR(ret < 0); ptr = ((void **) buffer)[0]; - value = (void *) kern_read(ptr); + value = (void *) readKernelMemory(ptr); *(void **) buffer = value; - sendwait(bss, clientfd, buffer, 4); + sendwait(bss, clientfd, buffer, sizeof(int)); break; } case COMMAND_TAKE_SCREEN_SHOT: { @@ -1271,7 +1272,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { bufferIndex += sizeof(bool); bool write = buffer[bufferIndex]; bufferIndex += sizeof(bool); - setDataAddressBreakPointRegister(address, read, write); + setDataBreakpoint(address, read, write); break; } @@ -1282,7 +1283,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { // Parse the address and set the breakpoint unsigned int address = ((unsigned int *) buffer)[0]; - setInstructionAddressBreakPointRegister(address); + setInstructionBreakpoint(address); break; } diff --git a/src/system/exception_handler.h b/src/system/exception_handler.h index d1dac63..f15f2a4 100644 --- a/src/system/exception_handler.h +++ b/src/system/exception_handler.h @@ -40,9 +40,10 @@ typedef struct OSContext { #define CPU_STACK_TRACE_DEPTH 10 -#define mfspr(_rn) \ +// http://elixir.free-electrons.com/linux/v2.6.24/source/include/asm-powerpc/reg.h#L713 +#define mfspr(spr) \ ({ register uint32_t _rval = 0; \ - asm volatile("mfspr %0," __stringify(_rn) \ + asm volatile("mfspr %0," __stringify(spr) \ : "=r" (_rval));\ _rval; \ }) diff --git a/src/utils/function_patcher.c b/src/utils/function_patcher.c new file mode 100644 index 0000000..18ed37a --- /dev/null +++ b/src/utils/function_patcher.c @@ -0,0 +1,404 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * With code from chadderz and dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include +#include "../utils/logger.h" +#include "../kernel/kernel_functions.h" +#include "function_patcher.h" + +#define CODE_RW_BASE_OFFSET 0x00000000 +#define DEBUG_LOG_DYN 1 + +void printFunctionHooks(FunctionHook *functionHooks, u32 functionHooksSize) { + for (unsigned int functionHookIndex = 0; functionHookIndex < functionHooksSize; functionHookIndex++) { + log_printf("Real address (%s): %08x\n", functionHooks[functionHookIndex].functionName, + functionHooks[functionHookIndex].realAddress); + } +} + +bool setRealAddress(FunctionHook functionHooks[], int functionHooksSize, const char *functionName, u32 address) { + for (int functionHookIndex = 0; functionHookIndex < functionHooksSize; functionHookIndex++) { + if (strncmp(functionName, functionHooks[functionHookIndex].functionName, 50) == 0) { + functionHooks[functionHookIndex].realAddress = address; + log_printf("Function %s defined with address %08x\n", functionHooks[functionHookIndex].functionName, + functionHooks[functionHookIndex].realAddress); + // printFunctionHooks(functionHooks, functionHooksSize); + + return true; + } + } + + return false; +} + +/* +* Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic. +* "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok. Orignal code by Chadderz. +*/ +void patchIndividualMethodHooks(FunctionHook *functionHook, int hook_information_size, + volatile unsigned int *dynamic_method_calls) { + log_printf("Patching %d given functions\n", hook_information_size); + /* Patch branches to it. */ + volatile unsigned int *space = &dynamic_method_calls[0]; + + int method_hooks_count = hook_information_size; + + u32 skipInstructionLength = 1; + u32 myInstructionLength = 6; + u32 instructionLength = myInstructionLength + skipInstructionLength; + u32 flush_len = 4 * instructionLength; + for (int functionIndex = 0; functionIndex < method_hooks_count; functionIndex++) { + log_printf("Patching %s...\n", functionHook[functionIndex].functionName); + if (functionHook[functionIndex].functionType == STATIC_FUNCTION && + functionHook[functionIndex].alreadyPatched == 1) { + if (isDynamicFunction((u32) OSEffectiveToPhysical((void *) functionHook[functionIndex].realAddress))) { + log_printf("The function %s is a dynamic function. Please fix that <3\n", + functionHook[functionIndex].functionName); + functionHook[functionIndex].functionType = DYNAMIC_FUNCTION; + } else { + log_printf("Skipping %s, its already patched\n", functionHook[functionIndex].functionName); + space += instructionLength; + continue; + } + } + + u32 physical = 0; + unsigned int replaceAddress = functionHook[functionIndex].replaceAddress; + unsigned int callAddress = functionHook[functionIndex].replaceCall; + + unsigned int realAddress = functionHook[functionIndex].realAddress; + + if (realAddress == 0) { + log_printf("The real address was NULL, we need to find it.\n"); + realAddress = getFunctionAddress(functionHook[functionIndex].library, + functionHook[functionIndex].functionName); + } else { + log_printf("The real address was not NULL! We patch it by the given address.\n"); + } + + if (realAddress == 0) { + log_printf("[Patch] OSDynLoad_FindExport failed for %s\n", functionHook[functionIndex].functionName); + space += instructionLength; + continue; + } + + if (DEBUG_LOG_DYN)log_printf("%s is located at %08X!\n", functionHook[functionIndex].functionName, realAddress); + + physical = (u32) OSEffectiveToPhysical((void *) realAddress); + if (!physical) { + log_printf("Error. Something is wrong with the physical address\n"); + space += instructionLength; + continue; + } + + if (DEBUG_LOG_DYN) + log_printf("%s physical is located at %08X!\n", functionHook[functionIndex].functionName, physical); + + *(volatile unsigned int *) (callAddress) = (unsigned int) (space) - CODE_RW_BASE_OFFSET; + + SC0x25_KernelCopyData((u32) space, physical, 4); + space++; + + //Only works if skip_instr == 1 + functionHook[functionIndex].realAddress = realAddress; + functionHook[functionIndex].restoreInstruction = *(space - 1); + if (DEBUG_LOG_DYN)log_printf("method_hooks[i].realAddr = %08X!\n", functionHook[functionIndex].realAddress); + if (DEBUG_LOG_DYN) + log_printf("method_hooks[i].restoreInstruction = %08X!\n", functionHook[functionIndex].restoreInstruction); + + //adding jump to real function thx @ dimok for the assembler code + /* + 90 61 ff e0 stw r3,-32(r1) + 3c 60 12 34 lis r3,4660 + 60 63 56 78 ori r3,r3,22136 + 7c 69 03 a6 mtctr r3 + 80 61 ff e0 lwz r3,-32(r1) + 4e 80 04 20 bctr*/ + *space = 0x9061FFE0; + space++; + *space = 0x3C600000 | (((realAddress + (skipInstructionLength * 4)) >> 16) & 0x0000FFFF); // lis r3, real_addr@h + space++; + *space = 0x60630000 | ((realAddress + (skipInstructionLength * 4)) & 0x0000ffff); // ori r3, r3, real_addr@l + space++; + *space = 0x7C6903A6; // mtctr r3 + space++; + *space = 0x8061FFE0; // lwz r3,-32(r1) + space++; + *space = 0x4E800420; // bctr + space++; + DCFlushRange((void *) (space - instructionLength), flush_len); + ICInvalidateRange((unsigned char *) (space - instructionLength), flush_len); + + //setting jump back + unsigned int replace_instr = 0x48000002 | (replaceAddress & 0x03fffffc); + DCFlushRange(&replace_instr, 4); + + SC0x25_KernelCopyData(physical, (u32) OSEffectiveToPhysical(&replace_instr), 4); + ICInvalidateRange((void *) (realAddress), 4); + + functionHook[functionIndex].alreadyPatched = 1; + log_printf("done!\n"); + } + + log_print("Done with patching given functions!\n"); +} + +void restoreIndividualInstructions(FunctionHook *functionHooks, int hook_information_size) { + log_printf("Restoring given functions!\n"); + int method_hooks_count = hook_information_size; + for (int functionIndex = 0; functionIndex < method_hooks_count; functionIndex++) { + log_printf("Restoring %s... ", functionHooks[functionIndex].functionName); + if (functionHooks[functionIndex].restoreInstruction == 0 || functionHooks[functionIndex].realAddress == 0) { + log_printf("I don't have the information for the restore =( skip\n"); + continue; + } + + unsigned int realAddress = functionHooks[functionIndex].realAddress; + + if (realAddress == 0) { + log_printf("The real address was NULL, we need to find it.\n"); + realAddress = getFunctionAddress(functionHooks[functionIndex].library, + functionHooks[functionIndex].functionName); + } else { + log_printf("The real address was not NULL! We patch it by the given address.\n"); + } + + if (!realAddress) { + log_printf("[Restore] OSDynLoad_FindExport failed for %s\n", functionHooks[functionIndex].functionName); + continue; + } + + u32 physical = (u32) OSEffectiveToPhysical((void *) realAddress); + if (!physical) { + log_printf("Something is wrong with the physical address\n"); + continue; + } + + if (isDynamicFunction((unsigned int) physical)) { + log_printf("Its a dynamic function. We don't need to restore it!\n", + functionHooks[functionIndex].functionName); + } else { + physical = (u32) OSEffectiveToPhysical( + (void *) functionHooks[functionIndex].realAddress); //When its an static function, we need to use the old location + if (DEBUG_LOG_DYN) + log_printf("Restoring %08X to %08X\n", (u32) functionHooks[functionIndex].restoreInstruction, physical); + SC0x25_KernelCopyData(physical, (u32) &functionHooks[functionIndex].restoreInstruction, 4); + if (DEBUG_LOG_DYN)log_printf("ICInvalidateRange %08X\n", (void *) functionHooks[functionIndex].realAddress); + ICInvalidateRange((void *) functionHooks[functionIndex].realAddress, 4); + log_printf("done\n"); + } + functionHooks[functionIndex].alreadyPatched = 0; // In case a + } + + KernelRestoreInstructions(); + log_print("Done with restoring given functions!\n"); +} + +bool isDynamicFunction(unsigned int physicalAddress) { + return (physicalAddress & 0x80000000) == 0x80000000; +} + +unsigned int getRPLHandle(int library, const char *functionName) { + unsigned int rplHandle = 0; + + switch (library) { + case LIB_CORE_INIT: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_CORE_INIT\n", functionName); + if (coreinit_handle == 0) { + log_print("LIB_CORE_INIT not acquired\n"); + return 0; + } + rplHandle = coreinit_handle; + break; + + case LIB_GX2: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_GX2\n", functionName); + unsigned int gx2_handle = 0; + OSDynLoad_Acquire("gx2.rpl", &gx2_handle); + if (gx2_handle == 0) { + log_print("LIB_GX2 not acquired\n"); + return 0; + } + rplHandle = gx2_handle; + break; + + /*case LIB_NSYSNET: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_NSYSNET\n", functionName); + if (nsysnet_handle == 0) { + log_print("LIB_NSYSNET not acquired\n"); + return 0; + } + rplHandle = nsysnet_handle; + break; + + case LIB_AOC: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_AOC\n", functionName); + if (aoc_handle == 0) { + log_print("LIB_AOC not acquired\n"); + return 0; + } + rplHandle = aoc_handle; + break; + + case LIB_AX: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_AX\n", functionName); + if (sound_handle == 0) { + log_print("LIB_AX not acquired\n"); + return 0; + } + rplHandle = sound_handle; + break;*/ + + case LIB_FS: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_FS\n", functionName); + if (coreinit_handle == 0) { + log_print("LIB_FS not acquired\n"); + return 0; + } + rplHandle = coreinit_handle; + break; + + case LIB_OS: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_OS\n", functionName); + if (coreinit_handle == 0) { + log_print("LIB_OS not acquired\n"); + return 0; + } + rplHandle = coreinit_handle; + break; + + /* + case LIB_PADSCORE: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_PADSCORE\n", functionName); + if (padscore_handle == 0) { + log_print("LIB_PADSCORE not acquired\n"); + return 0; + } + rplHandle = padscore_handle; + break; + + case LIB_SOCKET: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_SOCKET\n", functionName); + if (nsysnet_handle == 0) { + log_print("LIB_SOCKET not acquired\n"); + return 0; + } + rplHandle = nsysnet_handle; + break; + + case LIB_SYS: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_SYS\n", functionName); + if (sysapp_handle == 0) { + log_print("LIB_SYS not acquired\n"); + return 0; + } + rplHandle = sysapp_handle; + break; + + case LIB_VPAD: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_VPAD\n", functionName); + if (vpad_handle == 0) { + log_print("LIB_VPAD not acquired\n"); + return 0; + } + rplHandle = vpad_handle; + break; + + case LIB_NN_ACP: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_NN_ACP\n", functionName); + if (acp_handle == 0) { + log_print("LIB_NN_ACP not acquired\n"); + return 0; + } + rplHandle = acp_handle; + break; + + case LIB_SYSHID: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_SYSHID\n", functionName); + if (syshid_handle == 0) { + log_print("LIB_SYSHID not acquired\n"); + return 0; + } + rplHandle = syshid_handle; + break; + + case LIB_VPADBASE: + if (DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_VPADBASE\n", functionName); + if (vpadbase_handle == 0) { + log_print("LIB_VPADBASE not acquired\n"); + return 0; + } + rplHandle = vpadbase_handle; + break; */ + + default:; + char messageBuffer[50]; + __os_snprintf(messageBuffer, 50, "Unhandled library %i", library); + OSFatal(messageBuffer); + break; + } + + return rplHandle; +} + +unsigned int getFunctionAddress(unsigned int library, const char *functionName) { + unsigned int realAddress = 0; + + if (strcmp(functionName, "OSDynLoad_Acquire") == 0) { + memcpy(&realAddress, &OSDynLoad_Acquire, 4); + return realAddress; + } else if (strcmp(functionName, "LiWaitOneChunk") == 0) { + realAddress = (unsigned int) addr_LiWaitOneChunk; + return realAddress; + } else if (strcmp(functionName, "LiBounceOneChunk") == 0) { + //! not required on firmwares above 3.1.0 + if (OS_FIRMWARE >= 400) + return 0; + + unsigned int addr_LiBounceOneChunk = 0x010003A0; + realAddress = addr_LiBounceOneChunk; + return realAddress; + } + + unsigned int rpl_handle = getRPLHandle(library, functionName); + + if (!rpl_handle) { + log_printf("Failed to find the RPL handle for %s\n", functionName); + return 0; + } + + OSDynLoad_FindExport((u32) rpl_handle, 0, functionName, &realAddress); + + if (!realAddress) { + log_printf("[Get] OSDynLoad_FindExport failed for %s\n", functionName); + return 0; + } + + if ((u32) (*(volatile unsigned int *) (realAddress) & 0x48000002) == 0x48000000) { + unsigned int address_diff = (u32) (*(volatile unsigned int *) (realAddress) & 0x03FFFFFC); + if ((address_diff & 0x03000000) == 0x03000000) { + address_diff |= 0xFC000000; + } + realAddress += (int) address_diff; + if ((u32) (*(volatile unsigned int *) (realAddress) & 0x48000002) == 0x48000000) { + return 0; + } + } + + return realAddress; +} \ No newline at end of file diff --git a/src/utils/function_patcher.h b/src/utils/function_patcher.h new file mode 100644 index 0000000..37c1756 --- /dev/null +++ b/src/utils/function_patcher.h @@ -0,0 +1,123 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * With code from chadderz and dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef _FUNCTION_HOOKS_H_ +#define _FUNCTION_HOOKS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "../common/common.h" // OS_FIRMWARE + +// Library handles +#include "../dynamic_libs/aoc_functions.h" +#include "../dynamic_libs/ax_functions.h" +#include "../dynamic_libs/fs_functions.h" +#include "../dynamic_libs/gx2_functions.h" +#include "../dynamic_libs/os_functions.h" +#include "../dynamic_libs/padscore_functions.h" +#include "../dynamic_libs/socket_functions.h" +#include "../dynamic_libs/sys_functions.h" +#include "../dynamic_libs/vpad_functions.h" +/*#include "../dynamic_libs/acp_functions.h" +#include "../dynamic_libs/syshid_functions.h"*/ + +/* Macros for libs */ +#define LIB_CORE_INIT 0 +#define LIB_NSYSNET 1 +#define LIB_GX2 2 +#define LIB_AOC 3 +#define LIB_AX 4 +#define LIB_FS 5 +#define LIB_OS 6 +#define LIB_PADSCORE 7 +#define LIB_SOCKET 8 +#define LIB_SYS 9 +#define LIB_VPAD 10 +#define LIB_NN_ACP 11 +#define LIB_SYSHID 12 +#define LIB_VPADBASE 13 + +// functions types +#define STATIC_FUNCTION 0 +#define DYNAMIC_FUNCTION 1 + +/*enum Library { + LIB_CORE_INIT, + LIB_NSYSNET, + LIB_GX2, + LIB_AOC, + LIB_AX, + LIB_FS, + LIB_OS, + LIB_PADSCORE, + LIB_SOCKET, + LIB_SYS, + LIB_VPAD, + LIB_NN_ACP, + LIB_SYSHID, + LIB_VPADBASE +}; + +enum FunctionTypes { + STATIC_FUNCTION, + DYNAMIC_FUNCTION +};*/ + +// Original code by Chadderz +#define declareFunctionHook(returnType, functionName, ...) \ + returnType (* real_ ## functionName)(__VA_ARGS__) __attribute__((section(".data"))); \ + returnType my_ ## functionName(__VA_ARGS__) + +#define declareGameFunctionHook(functionName) { (unsigned int) my_ ## functionName, (unsigned int) &real_ ## functionName, 0, # functionName,0,0,1,0} + +#define makeFunctionHook(functionName, library, functionType) { (unsigned int) my_ ## functionName, (unsigned int) &real_ ## functionName, library, # functionName,0,0,functionType,0} + +#define FUNCTION_PATCHER_METHOD_STORE_SIZE 7 + +typedef struct { + const unsigned int replaceAddress; + const unsigned int replaceCall; + const unsigned int library; + const char functionName[50]; + unsigned int realAddress; + unsigned int restoreInstruction; + unsigned char functionType; + unsigned char alreadyPatched; +} FunctionHook; + +void printFunctionHooks(FunctionHook *functionHooks, u32 functionHooksSize); + +bool setRealAddress(FunctionHook functionHooks[], int functionHooksSize, const char *functionName, u32 address); + +void patchIndividualMethodHooks(FunctionHook *functionHook, int hook_information_size, + volatile unsigned int *dynamic_method_calls); + +void restoreIndividualInstructions(FunctionHook *functionHooks, int hook_information_size); + +unsigned int getFunctionAddress(unsigned int library, const char *functionName); + +bool isDynamicFunction(unsigned int physicalAddress); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/utils/logger.h b/src/utils/logger.h index dd7cc71..d4b22fe 100644 --- a/src/utils/logger.h +++ b/src/utils/logger.h @@ -6,6 +6,7 @@ extern "C" { #endif #define DEBUG_LOGGER 1 +#define COMPUTER_IP_ADDRESS "192.168.2.103" #ifdef DEBUG_LOGGER void log_init(const char * ip); diff --git a/tcpgecko.elf b/tcpgecko.elf index 423b2e3..0696c2a 100644 Binary files a/tcpgecko.elf and b/tcpgecko.elf differ