2 Copyright 2009-2010, Ifcaro, jimmikaelkael & Polo
3 Copyright 2006-2008 Polo
4 Licenced under Academic Free License version 3.0
5 Review OpenUsbLd README & LICENSE files for further details.
7 Some parts of the code are taken from HD Project by Polo
20 #include <syscallnr.h>
22 #include <ps2_reg_defs.h>
24 extern void *cddev_irx
;
25 extern int size_cddev_irx
;
30 char *g_argv
[1 + MAX_ARGS
];
31 static char g_ElfPath
[1024];
32 static void *g_patchInitializeUserMem_addr
;
33 static u32 g_patchInitializeUserMem_val
;
37 int iop_reboot_count
= 0;
39 int padOpen_hooked
= 0;
41 static u32 systemRestartpattern
[] = {
43 0x0c000000, // jal restartEE()
45 0x8fa30010, // lw v1, $0010(sp)
46 0x0240302d, // daddu a2, s2, zero
47 0x8fa50014, // lw a1, $0014(sp)
48 0x8c67000c, // lw a3, $000c(v1)
49 0x18e00009, // blez a3, 2f
50 0x0000202d, // daddu a0, zero, zero
52 0x8ca30000, // lw v1, $0000(a1)
53 0x24840004, // addiu a0, a0, $0004
54 0x24a50004, // addiu a1, a1, $0004
55 0x0087102a, // slt v0, a0, a3
56 0xacc30000 // sw v1, $0000(a2)
58 static u32 systemRestartpattern_mask
[] = {
76 static void (*systemRestart
)(void);
78 static u32 InitializeUserMempattern
[] = {
79 0x27bdffe0, // addiu sp, sp, $ffe0
80 0xffb00000, // sd s0, $0000(sp)
81 0xffbf0010, // sd ra, $0010(sp)
82 0x0c000000, // jal GetMemorySize
83 0x00000000, // daddu s0, a0, zero <-- some modchips are patching here, so we'll repatch
84 0x0040202d, // daddu a0, v0, zero
85 0x0204102b, // sltu v0, s0, a0
86 0x1040000a, // beq v0, zero, 2f
87 0xdfbf0010, // ld ra, $0010(sp)
88 0x700014a9, // por v0, zero, zero
89 0x7e020000, // sq v0, $0000(s0)
90 0x26100010, // addiu s0, s0, $10
91 0x0204102b, // sltu v0, s0, a0
94 0x1440fffa, // bne v0, zero, 1b
95 0x700014a9 // por v0, zero, zero
97 0xdfbf0010, // ld ra, $0010(sp)
98 0xdfbf0000, // ld s0, $0000(sp)
100 0x27bd0020 // addiu sp, sp, $0020
104 static u32 InitializeUserMempattern_mask
[] = {
124 static u32 InitializeTLBpattern
[] = {
125 0x3c027000, // lui v0, $7000
126 0x8c423ff0, // lw v0, $3ff0(v0)
127 0x3c038001, // lui v1, $8001
128 0xac620000, // sw v0, $XXXX(v1)
129 0x3c02bfc0, // lui v0, $bfc0
130 0x8c4201f8, // lw v0, $01f8(v0)
131 0x3c038001, // lui v1, $8001
132 0xac620000, // sw v0, $XXXX(v1)
133 0x3c1d8000, // lui sp, $800X
134 0x27bd0000, // addiu sp, sp, $XXXX
135 0x0c000000, // jal InitializeTLB
138 static u32 InitializeTLBpattern_mask
[] = {
153 void (*InitializeTLB
)(void);
156 /*----------------------------------------------------------------------------------------*/
157 /* This fonction is call when SifSetDma catch a reboot request. */
158 /*----------------------------------------------------------------------------------------*/
159 u32
New_SifSetDma(SifDmaTransfer_t
*sdd
, s32 len
)
161 // Hook padOpen function to install In Game Reset
162 if( !(g_compat_mask
& COMPAT_MODE_6
) && padOpen_hooked
== 0 )
163 padOpen_hooked
= Install_PadOpen_Hook(0x00100000, 0x01ff0000, PADOPEN_HOOK
);
165 SifCmdResetData
*reset_pkt
= (SifCmdResetData
*)sdd
->src
;
168 New_Reset_Iop(reset_pkt
->arg
, reset_pkt
->flag
);
173 /*----------------------------------------------------------------------------------------*/
174 /* This fonction replace SifSetDma syscall in kernel. */
175 /*----------------------------------------------------------------------------------------*/
177 u32 Hook_SifSetDma(SifDmaTransfer_t *sdd, s32 len)
179 if((sdd->attr == 0x44) && ((sdd->size==0x68) || (sdd->size==0x70))) {
181 SifCmdResetData *reset_pkt = (SifCmdResetData*)sdd->src;
182 if(((reset_pkt->chdr.psize == 0x68) || (reset_pkt->chdr.psize == 0x70)) && (reset_pkt->chdr.fcode == 0x80000003)) {
184 __asm__ __volatile__ (
185 "la $v1, _SifSetDma\n\t"
192 __asm__ __volatile__ (
196 ::"r"((u32)Old_SifSetDma), "r"((u32)sdd), "r"((u32)len)
203 /*----------------------------------------------------------------------------------------*/
204 /* This fonction unhook SifSetDma/SifSetReg sycalls */
205 /*----------------------------------------------------------------------------------------*/
207 void Apply_Mode3(void)
209 SetSyscall(__NR_SifSetDma, Old_SifSetDma);
210 SetSyscall(__NR_SifSetReg, Old_SifSetReg);
215 /*----------------------------------------------------------------------------------------*/
216 /* This fonction replace SifSetReg syscall in kernel. */
217 /*----------------------------------------------------------------------------------------*/
219 int Hook_SifSetReg(u32 register_num, int register_value)
225 if (set_reg_hook == 0) {
228 GS_BGCOLOUR = 0x000000;
230 // We should have a mode to do this: this is corresponding to HD-Loader's mode 3
231 if ((g_compat_mask & COMPAT_MODE_3) && (iop_reboot_count == 2)) {
232 __asm__ __volatile__ (
233 "la $v1, Apply_Mode3\n\t"
243 __asm__ __volatile__ (
247 ::"r"((u32)Old_SifSetReg), "r"((u32)register_num), "r"((u32)register_value)
254 // ------------------------------------------------------------------------
255 static void init_systemRestart(void)
262 // scan to find kernel InitializeUserMemory()
263 ptr
= (u32
*)0x80001000;
264 ptr
= find_pattern_with_mask(ptr
, 0x7f000, InitializeUserMempattern
, InitializeUserMempattern_mask
, sizeof(InitializeUserMempattern
));
267 // keep original opcode address and value
268 g_patchInitializeUserMem_addr
= (void *)&ptr
[4];
269 g_patchInitializeUserMem_val
= ptr
[4];
270 // patch InitializeUserMemory() to avoid user mem to be cleared
271 _sw(0x3c100200, (u32
)g_patchInitializeUserMem_addr
); // it will exit at first s0/a0 comparison
273 // scan to find kernel systemRestart() function
274 ptr
= (u32
*)0x80001000;
275 ptr
= find_pattern_with_mask(ptr
, 0x7f000, systemRestartpattern
, systemRestartpattern_mask
, sizeof(systemRestartpattern
));
278 // get systemRestart function pointer
279 systemRestart
= (void *)(((ptr
[1] & 0x03ffffff) << 2) | 0x80000000);
281 // scan to find kernel InitializeTLB() function
282 ptr
= (u32
*)0x80001000;
283 ptr
= find_pattern_with_mask(ptr
, 0x7f000, InitializeTLBpattern
, InitializeTLBpattern_mask
, sizeof(InitializeTLBpattern
));
286 // get InitializeTLB function pointer
287 InitializeTLB
= (void *)(((ptr
[10] & 0x03ffffff) << 2) | 0x80000000);
297 GS_BGCOLOUR
= 0x0000ff; // hangs on red screen
301 // ------------------------------------------------------------------------
302 static void deinit_systemRestart(void)
307 // unpatch InitializeUserMemory()
308 _sw(g_patchInitializeUserMem_val
, (u32
)g_patchInitializeUserMem_addr
);
316 // ------------------------------------------------------------------------
322 DPRINTF("t_loadElf()\n");
328 DPRINTF("t_loadElf: Resetting IOP...\n");
330 set_reg_disabled
= 0;
331 New_Reset_Iop("rom0:UDNL rom0:EELOADCNF", 0);
332 set_reg_disabled
= 1;
334 iop_reboot_count
= 1;
339 DPRINTF("t_loadElf: Loading cddev IOP module...\n");
340 LoadIRXfromKernel(cddev_irx
, size_cddev_irx
, 0, NULL
);
342 strncpy(g_ElfPath
, g_argv
[0], 1024);
344 DPRINTF("t_loadElf: elf path = '%s'\n", g_ElfPath
);
346 // replacing cdrom in elf path by cddev
347 if (_strstr(g_argv
[0], "cdrom")) {
348 u8
*ptr
= (u8
*)g_argv
[0];
349 _strcpy(g_ElfPath
, "cddev");
350 _strcat(g_ElfPath
, &ptr
[5]);
353 DPRINTF("t_loadElf: elf path = '%s'\n", g_ElfPath
);
355 DPRINTF("t_loadElf: System Restart...\n");
359 while (!(*(vu32
*)R_EE_SBUS_SMFLAG
& SBUS_CTRL_MSINT
)) {;}
360 *(vu32
*)R_EE_SBUS_SMFLAG
= SBUS_CTRL_MSINT
;
365 GS_BGCOLOUR
= 0x00ff00;
367 DPRINTF("t_loadElf: cleaning user memory...");
370 for (i
= 0x00100000; i
< 0x02000000; i
+= 64) {
371 __asm__
__volatile__ (
381 DPRINTF("t_loadElf: loading elf...");
382 r
= LoadElf(g_ElfPath
, &elf
);
384 if ((!r
) && (elf
.epc
)) {
387 DPRINTF("t_loadElf: exiting services...\n");
394 // replacing cddev in elf path by cdrom
395 if (_strstr(g_ElfPath
, "cddev"))
396 memcpy(g_ElfPath
, "cdrom", 5);
398 DPRINTF("t_loadElf: real elf path = '%s'\n", g_ElfPath
);
400 DPRINTF("t_loadElf: trying to apply patches...\n");
401 // applying needed patches
407 DPRINTF("t_loadElf: executing...\n");
408 ExecPS2((void*)elf
.epc
, (void*)elf
.gp
, g_argc
, g_argv
);
411 DPRINTF(" failed\n");
414 GS_BGCOLOUR
= 0xffffff; // white screen: error
418 // ------------------------------------------------------------------------
420 int Hook_CreateThread(ee_thread_t *thread_param)
422 // Hook padOpen function to install In Game Reset
423 if( padOpen_hooked == 0 && ( thread_param->initial_priority == 0 || (thread_param->initial_priority < 5 && thread_param->current_priority == 0) ) )
424 padOpen_hooked = Install_PadOpen_Hook(0x00100000, 0x01ff0000, PADOPEN_HOOK);
426 return Old_CreateThread(thread_param);
430 // ------------------------------------------------------------------------
432 int Hook_ExecPS2(void *entry, void *gp, int num_args, char *args[])
434 // Hook padOpen function to install In Game Reset
435 if( (u32)entry >= 0x00100000 )
436 padOpen_hooked = Install_PadOpen_Hook( 0x00100000, 0x01ff0000, PADOPEN_HOOK );
438 __asm__ __volatile__ (
444 ::"r"((u32)Old_ExecPS2), "r"((u32)entry), "r"((u32)gp), "r"((u32)num_args), "r"((u32)args)
451 /*----------------------------------------------------------------------------------------*/
452 /* Replace SifSetDma, SifSetReg, LoadExecPS2 syscalls in kernel. (Game Loader) */
453 /* Replace CreateThread and ExecPS2 syscalls in kernel. (In Game Reset) */
454 /*----------------------------------------------------------------------------------------*/
455 void Install_Kernel_Hooks(void)
457 init_systemRestart();
459 Old_SifSetDma
= GetSyscallHandler(__NR_SifSetDma
);
460 SetSyscall(__NR_SifSetDma
, &Hook_SifSetDma
);
462 Old_SifSetReg
= GetSyscallHandler(__NR_SifSetReg
);
463 SetSyscall(__NR_SifSetReg
, &Hook_SifSetReg
);
465 Old_LoadExecPS2
= GetSyscallHandler(__NR_LoadExecPS2
);
466 SetSyscall(__NR_LoadExecPS2
, &Hook_LoadExecPS2
);
468 // If IGR is enabled hook ExecPS2 & CreateThread syscalls
469 if(!(g_compat_mask
& COMPAT_MODE_6
))
471 Old_CreateThread
= GetSyscallHandler(__NR_CreateThread
);
472 SetSyscall(__NR_CreateThread
, &Hook_CreateThread
);
474 Old_ExecPS2
= GetSyscallHandler(__NR_ExecPS2
);
475 SetSyscall(__NR_ExecPS2
, &Hook_ExecPS2
);
479 /*----------------------------------------------------------------------------------------*/
480 /* Restore original SifSetDma, SifSetReg, LoadExecPS2 syscalls in kernel. (Game loader) */
481 /* Restore original CreateThread and ExecPS2 syscalls in kernel. (In Game Reset) */
482 /*----------------------------------------------------------------------------------------*/
483 void Remove_Kernel_Hooks(void)
485 deinit_systemRestart();
487 SetSyscall(__NR_SifSetDma
, Old_SifSetDma
);
488 SetSyscall(__NR_SifSetReg
, Old_SifSetReg
);
489 SetSyscall(__NR_LoadExecPS2
, Old_LoadExecPS2
);
491 // If IGR is enabled unhook ExecPS2 & CreateThread syscalls
492 if(!(g_compat_mask
& COMPAT_MODE_6
))
494 SetSyscall(__NR_CreateThread
, Old_CreateThread
);
495 SetSyscall(__NR_ExecPS2
, Old_ExecPS2
);