mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-12-23 10:21:55 +01:00
515 lines
14 KiB
C
515 lines
14 KiB
C
#include "mload_modules.h"
|
|
#include "filelist.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);
|
|
}
|
|
}
|
|
//////////////////////////////////
|
|
|