usbloadergx/source/mload/mload_modules.c

501 lines
12 KiB
C
Raw Normal View History

#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);
}
}
//////////////////////////////////