#include "mload_modules.h" #include "ehcmodule_frag_v4_bin.h" #include "ehcmodule_frag_v5_bin.h" #include "gecko.h" #define ALIGNED(x) __attribute__((aligned(x))) #define DEBUG_MLOAD /* Used for Hermes NAND emulation */ int global_mount; int sd_ok = 0; int ud_ok = 0; static u32 ios_36[16] ATTRIBUTE_ALIGN( 32 ) = { 0, // DI_EmulateCmd 0, 0x2022DDAC, // dvd_read_controlling_data 0x20201010 + 1, // handle_di_cmd_reentry (thumb) 0x20200b9c + 1, // ios_shared_alloc_aligned (thumb) 0x20200b70 + 1, // ios_shared_free (thumb) 0x20205dc0 + 1, // ios_memcpy (thumb) 0x20200048 + 1, // ios_fatal_di_error (thumb) 0x20202b4c + 1, // ios_doReadHashEncryptedState (thumb) 0x20203934 + 1, // ios_printf (thumb) }; static u32 ios_38[16] ATTRIBUTE_ALIGN( 32 ) = { 0, // DI_EmulateCmd 0, 0x2022cdac, // dvd_read_controlling_data 0x20200d38 + 1, // handle_di_cmd_reentry (thumb) 0x202008c4 + 1, // ios_shared_alloc_aligned (thumb) 0x20200898 + 1, // ios_shared_free (thumb) 0x20205b80 + 1, // ios_memcpy (thumb) 0x20200048 + 1, // ios_fatal_di_error (thumb) 0x20202874 + 1, // ios_doReadHashEncryptedState (thumb) 0x2020365c + 1, // ios_printf (thumb) }; static u32 ios_37[16] ATTRIBUTE_ALIGN( 32 ) = { 0, // DI_EmulateCmd 0, 0x2022DD60, // dvd_read_controlling_data 0x20200F04 + 1, // handle_di_cmd_reentry (thumb) 0x2020096C + 1, // ios_shared_alloc_aligned (thumb) 0x2020093C + 1, // ios_shared_free (thumb) 0x20205E54 + 1, // ios_memcpy (thumb) 0x20200048 + 1, // ios_fatal_di_error (thumb) 0x20202A70 + 1, // ios_doReadHashEncryptedState (thumb) 0x2020387C + 1, // ios_printf (thumb) }; static u32 ios_57[16] ATTRIBUTE_ALIGN( 32 ) = { 0, // DI_EmulateCmd 0, 0x2022cd60, // dvd_read_controlling_data 0x20200f04 + 1, // handle_di_cmd_reentry (thumb) 0x2020096c + 1, // ios_shared_alloc_aligned (thumb) // no usado 0x2020093C + 1, // ios_shared_free (thumb) // no usado 0x20205EF0 + 1, // ios_memcpy (thumb) 0x20200048 + 1, // ios_fatal_di_error (thumb) 0x20202944 + 1, // ios_doReadHashEncryptedState (thumb) 0x20203750 + 1, // ios_printf (thumb) }; static u32 ios_60[16] ATTRIBUTE_ALIGN( 32 ) = { 0, // DI_EmulateCmd 0, 0x2022cd60, // dvd_read_controlling_data 0x20200f04 + 1, // handle_di_cmd_reentry (thumb) 0x2020096c + 1, // ios_shared_alloc_aligned (thumb) // no usado 0x2020093C + 1, // ios_shared_free (thumb) // no usado 0x20205e00 + 1, // ios_memcpy (thumb) 0x20200048 + 1, // ios_fatal_di_error (thumb) 0x20202944 + 1, // ios_doReadHashEncryptedState (thumb) 0x20203750 + 1, // ios_printf (thumb) }; u32 patch_datas[8] ATTRIBUTE_ALIGN( 32 ); data_elf my_data_elf; void *external_ehcmodule = NULL; int size_external_ehcmodule = 0; static int my_thread_id = 0; int load_ehc_module() { int is_ios = 0; #if 0 FILE *fp; // WARNING!!!: load external module suspended if ( sd_ok && !external_ehcmodule ) { fp = fopen( "sd:/apps/usbloader_gx/ehcmodule.elf", "rb" ); if ( fp == NULL ) fp = fopen( "sd:/apps/usbloadergx/ehcmodule.elf", "rb" ); if ( fp != 0 ) { fseek( fp, 0, SEEK_END ); size_external_ehcmodule = ftell( fp ); external_ehcmodule = memalign( 32, size_external_ehcmodule ); if ( !external_ehcmodule ) {fclose( fp );} else { fseek( fp, 0, SEEK_SET ); if ( fread( external_ehcmodule, 1, size_external_ehcmodule , fp ) != size_external_ehcmodule ) {free( external_ehcmodule ); external_ehcmodule = NULL;} fclose( fp ); } } } #endif /* if(mload_init()<0) return -1; mload_elf((void *) logmodule, &my_data_elf); my_thread_id= mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio); if(my_thread_id<0) return -1; */ if ( !external_ehcmodule ) { #ifdef DEBUG_MLOAD gprintf( "before mload_init\n" ); #endif if ( mload_init() < 0 ) return -1; #ifdef DEBUG_MLOAD gprintf( "after mload_init\n" ); #endif if ( IOS_GetRevision() == 4 ) { #ifdef DEBUG_MLOAD gprintf( "Loading ehcmodule v4\n" ); #endif mload_elf( ( void * ) ehcmodule_frag_v4_bin, &my_data_elf ); } else if ( IOS_GetRevision() == 65535 ) { #ifdef DEBUG_MLOAD gprintf( "Loading ehcmodule v5\n" ); #endif mload_elf( ( void * ) ehcmodule_frag_v5_bin, &my_data_elf ); } else { return -2; } // mload_elf((void *) ehcmodule, &my_data_elf); #ifdef DEBUG_MLOAD gprintf( "before mload_run_thread\n" ); #endif my_thread_id = mload_run_thread( my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio ); if ( my_thread_id < 0 ) return -1; //if(mload_module(ehcmodule, size_ehcmodule)<0) return -1; } else { //if(mload_module(external_ehcmodule, size_external_ehcmodule)<0) return -1; if ( mload_init() < 0 ) return -1; mload_elf( ( void * ) external_ehcmodule, &my_data_elf ); my_thread_id = mload_run_thread( my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio ); if ( my_thread_id < 0 ) return -1; } usleep( 350*1000 ); // Test for IOS #if 0 mload_seek( 0x20207c84, SEEK_SET ); mload_read( patch_datas, 32 ); if ( patch_datas[0] == 0x6e657665 ) { is_ios = 38; } else { is_ios = 36; } #endif is_ios = mload_get_IOS_base(); switch ( is_ios ) { case 36: memcpy( ios_36, dip_plugin, 4 ); // copy the entry_point memcpy( dip_plugin, ios_36, 4*10 ); // copy the adresses from the array mload_seek( 0x1377E000, SEEK_SET ); // copy dip_plugin in the starlet mload_write( dip_plugin, size_dip_plugin ); // enables DIP plugin mload_seek( 0x20209040, SEEK_SET ); mload_write( ios_36, 4 ); break; case 37: memcpy( ios_37, dip_plugin, 4 ); // copy the entry_point memcpy( dip_plugin, ios_37, 4*10 ); // copy the adresses from the array mload_seek( 0x1377E000, SEEK_SET ); // copy dip_plugin in the starlet mload_write( dip_plugin, size_dip_plugin ); // enables DIP plugin mload_seek( 0x20209030, SEEK_SET ); mload_write( ios_37, 4 ); break; case 38: memcpy( ios_38, dip_plugin, 4 ); // copy the entry_point memcpy( dip_plugin, ios_38, 4*10 ); // copy the adresses from the array mload_seek( 0x1377E000, SEEK_SET ); // copy dip_plugin in the starlet mload_write( dip_plugin, size_dip_plugin ); // enables DIP plugin mload_seek( 0x20208030, SEEK_SET ); mload_write( ios_38, 4 ); break; case 57: memcpy( ios_57, dip_plugin, 4 ); // copy the entry_point memcpy( dip_plugin, ios_57, 4*10 ); // copy the adresses from the array mload_seek( 0x1377E000, SEEK_SET ); // copy dip_plugin in the starlet mload_write( dip_plugin, size_dip_plugin ); // enables DIP plugin mload_seek( 0x20208030, SEEK_SET ); mload_write( ios_57, 4 ); break; case 60: memcpy( ios_60, dip_plugin, 4 ); // copy the entry_point memcpy( dip_plugin, ios_60, 4*10 ); // copy the adresses from the array mload_seek( 0x1377E000, SEEK_SET ); // copy dip_plugin in the starlet mload_write( dip_plugin, size_dip_plugin ); // enables DIP plugin mload_seek( 0x20208030, SEEK_SET ); mload_write( ios_60, 4 ); break; } mload_close(); return 0; } #define IOCTL_FAT_MOUNTSD 0xF0 #define IOCTL_FAT_UMOUNTSD 0xF1 #define IOCTL_FAT_MOUNTUSB 0xF2 #define IOCTL_FAT_UMOUNTUSB 0xF3 #define IOCTL_FFS_MODE 0x80 int load_fatffs_module( u8 *discid ) { static char fs[] ATTRIBUTE_ALIGN( 32 ) = "fat"; s32 hid = -1, fd = -1; static char file_name[256] ALIGNED( 0x20 ) = "SD:"; int n; char *p; s32 ret; p = &file_name[0]; if ( mload_init() < 0 ) return -1; mload_elf( ( void * ) fatffs_module_bin, &my_data_elf ); my_thread_id = mload_run_thread( my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio ); if ( my_thread_id < 0 ) return -1; global_mount &= ~0xc; if ( discid ) { sd_ok = ud_ok = 1; /* Function get_fat_name not implemented, this should return the path to the save file */ // p=get_fat_name(discid); p = NULL; sd_ok = ud_ok = 0; if ( !p ) return -1; global_mount &= ~0xf; // change 'ud:' by 'usb:' if ( p[0] == 'U' ) {global_mount |= 2; file_name[0] = 'U'; file_name[1] = 'S'; file_name[2] = 'B'; memcpy( file_name + 3, ( void * )p + 2, 253 );} else {global_mount |= 1; memcpy( file_name, ( void * ) p, 256 );} // copy filename to dip_plugin filename area mload_seek( *( ( u32 * ) ( dip_plugin + 14*4 ) ), SEEK_SET ); // offset 14 (filename Address - 256 bytes) mload_write( file_name, sizeof( file_name ) ); mload_close(); } else { if ( ( global_mount & 3 ) == 0 ) return 0; if ( global_mount & 1 ) p[0] = 's'; if ( global_mount & 2 ) p[0] = 'u'; } usleep( 350*1000 ); /* Create heap */ if ( hid < 0 ) { hid = iosCreateHeap( 0x100 ); if ( hid < 0 ) return -1; } /* Open USB device */ fd = IOS_Open( fs, 0 ); if ( fd < 0 ) { if ( hid >= 0 ) { iosDestroyHeap( hid ); hid = -1; } return -1; } n = 30; // try 20 times while ( n > 0 ) { if ( ( global_mount & 10 ) == 2 ) {ret = IOS_IoctlvFormat( hid, fd, IOCTL_FAT_MOUNTUSB, ":" ); if ( ret == 0 ) global_mount |= 8;} else {ret = IOS_IoctlvFormat( hid, fd, IOCTL_FAT_MOUNTSD, ":" ); if ( ret == 0 ) {global_mount |= 4;}} if ( ( global_mount & 7 ) == 3 && ret == 0 ) {ret = IOS_IoctlvFormat( hid, fd, IOCTL_FAT_MOUNTSD, ":" ); if ( ret == 0 ) global_mount |= 4;} if ( ( global_mount & 3 ) == ( ( global_mount >> 2 ) & 3 ) && ( global_mount & 3 ) ) {ret = 0; break;} else ret = -1; //ret=IOS_IoctlvFormat(hid, fd, IOCTL_FAT_MOUNTSD, ":"); //if(ret==0) break; usleep( 500*1000 ); n--; } if ( fd >= 0 ) { IOS_Close( fd ); fd = -1; } if ( hid >= 0 ) { iosDestroyHeap( hid ); hid = -1; } if ( n == 0 ) return -1; return 0; } int enable_ffs( int mode ) { static char fs[] ATTRIBUTE_ALIGN( 32 ) = "fat"; s32 hid = -1, fd = -1; s32 ret; /* Create heap */ if ( hid < 0 ) { hid = iosCreateHeap( 0x100 ); if ( hid < 0 ) return -1; } /* Open USB device */ fd = IOS_Open( fs, 0 ); if ( fd < 0 ) { if ( hid >= 0 ) { iosDestroyHeap( hid ); hid = -1; } return -1; } ret = IOS_IoctlvFormat( hid, fd, IOCTL_FFS_MODE, "i:", mode ); if ( fd >= 0 ) { IOS_Close( fd ); fd = -1; } if ( hid >= 0 ) { iosDestroyHeap( hid ); hid = -1; } return ret; } void enable_ES_ioctlv_vector( void ) { patch_datas[0] = *( ( u32 * ) ( dip_plugin + 16 * 4 ) ); mload_set_ES_ioctlv_vector( ( void * ) patch_datas[0] ); } void Set_DIP_BCA_Datas( u8 *bca_data ) { // write in dip_plugin bca data area mload_seek( *( ( u32 * ) ( dip_plugin + 15*4 ) ), SEEK_SET ); // offset 15 (bca_data area) mload_write( bca_data, 64 ); mload_close(); } u8 *search_for_ehcmodule_cfg( u8 *p, int size ) { int n; for ( n = 0; n < size; n++ ) { if ( !memcmp( ( void * ) &p[n], "EHC_CFG", 8 ) && p[n+8] == 0x12 && p[n+9] == 0x34 && p[n+10] == 0x00 && p[n+11] == 0x01 ) { return &p[n]; } } return NULL; } void test_and_patch_for_port1() { // test for port 1 u8 * ehc_data = NULL; if ( IOS_GetRevision() == 4 ) { ehc_data = search_for_ehcmodule_cfg( ( void * ) ehcmodule_frag_v4_bin, ehcmodule_frag_v4_bin_size ); } else if ( IOS_GetRevision() == 65535 ) { ehc_data = search_for_ehcmodule_cfg( ( void * ) ehcmodule_frag_v5_bin, ehcmodule_frag_v5_bin_size ); } if ( ehc_data ) { ehc_data += 12; use_port1 = ehc_data[0]; } if ( use_port1 ) // release port 0 and use port 1 { u32 dat = 0; u32 addr; // get EHCI base registers mload_getw( ( void * ) 0x0D040000, &addr ); addr &= 0xff; addr += 0x0D040000; mload_getw( ( void * ) ( addr + 0x44 ), &dat ); if ( ( dat & 0x2001 ) == 1 ) mload_setw( ( void * ) ( addr + 0x44 ), 0x2000 ); mload_getw( ( void * ) ( addr + 0x48 ), &dat ); if ( ( dat & 0x2000 ) == 0x2000 ) mload_setw( ( void * ) ( addr + 0x48 ), 0x1001 ); } } //////////////////////////////////