PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
patch_fileio.c
1#include <tamtypes.h>
2#include <kernel.h>
3#include <sifrpc.h>
4#include <iopheap.h>
5#include <string.h>
6
7#include "slib.h"
8#include "smod.h"
9
10#include "common.h"
11
12#define JMP(addr) (0x08000000|(0x3ffffff&((addr)>>2)))
13#define JAL(addr) (0x0c000000 | (0x3ffffff & ((addr) >> 2)))
14
16{
17 /* This patch is a fix for FILEIO on the IOP:
18 The handler of rpc_fioremove doesn't exit right after file is
19 removed due to the break being missing, which ends up
20 calling the mkdir RPC handler in succession.
21 A folder with the same name as the deleted file will be created.
22 We'll search for FILEIO text section start and patch the rpc
23 handler to jump to a subroutine to correct this.
24
25 The RPC handlers for getstat() and dread() do not suspend interrupts
26 before invoking sceSifSetDma(), which may result in a race condition
27 that destroys the internal SIF data structure within SIFMAN. */
28
29 smod_mod_info_t mod_info;
31 static u32 new_fileio[20] ALIGNED(16)={
32 //sceFioRemove fix
33 0x0c0001ce, // jal +0x738 <- jal fio_remove
34 0x00000000, // nop
35 0x0800033a, // j +0xce8 <- j rpc_handler_exit
36 0x00000000, // nop
37 //sceFioGetstat()/sceFioDread() fix
38 0x27bdfff0, // addiu sp,sp,-16
39 0xafbf0000, // sw ra,0(sp)
40 0xafa40004, // sw a0,4(sp)
41 0xafa50008, // sw a1,8(sp)
42 0x0c000423, // jal +0x108c <- jal CpuSuspendIntr
43 0x27a4000c, // addiu a0,sp,12
44 0x8fa40004, // lw a0,4(sp)
45 0x0c000430, // jal +0x10c0 <- jal sceSifSetDma
46 0x8fa50008, // lw a1,8(sp)
47 0x8fa4000c, // lw a0,12(sp)
48 0x0c000425, // jal +0x1094 <- jal CpuResumeIntr
49 0xafa20004, // sw v0,4(sp)
50 0x8fbf0000, // lw ra,0(sp)
51 0x8fa20004, // lw v0,4(sp)
52 0x03e00008, // jr ra
53 0x27bd0010, // addiu sp,sp,16
54 };
55 u32 *p_new_fileio;
56 u32 new_jump_op;
57 void *patch_addr;
58
59 memset(&mod_info, 0, sizeof(mod_info));
60 int ret = smod_get_mod_by_name("FILEIO_service", &mod_info);
61 if ((!ret) || (mod_info.version != 0x101))
62 return -1;
63
64 SifInitIopHeap();
65 if((patch_addr = SifAllocIopHeap(sizeof(new_fileio))) == NULL)
66 return -1;
67
68 /* setup our jump opcodes */
69 p_new_fileio = UNCACHED_SEG(new_fileio);
70
71 //For the sceFioRemove() patch
72 p_new_fileio[0] += ((u32)mod_info.text_start >> 2);
73 p_new_fileio[2] += ((u32)mod_info.text_start >> 2);
74
75 //For the sceFioGetstat() and sceFioDread() patch
76 p_new_fileio[8] += ((u32)mod_info.text_start >> 2);
77 p_new_fileio[11] += ((u32)mod_info.text_start >> 2);
78 p_new_fileio[14] += ((u32)mod_info.text_start >> 2);
79
80 /* apply it */
81 dmat.src=new_fileio;
82 dmat.dest=patch_addr;
83 dmat.size=sizeof(new_fileio);
84 dmat.attr=0;
85 SifSetDma(&dmat, 1);
86
87 //For the dump to sceRemove()
88 new_jump_op = JMP((u32)patch_addr);
89 smem_write_word((void *)((u8 *)mod_info.text_start + 0x0bb8), new_jump_op);
90 new_jump_op = JAL((u32)patch_addr + 16);
91 //For the jumps to sceSifSetDma within sceGetstat() and sceDread():
92 smem_write_word((void *)((u8 *)mod_info.text_start + 0x09cc), new_jump_op);
93 smem_write_word((void *)((u8 *)mod_info.text_start + 0x0a58), new_jump_op);
94
95 return 0;
96}
int sbv_patch_fileio(void)
int smod_get_mod_by_name(const char *name, smod_mod_info_t *info)
Definition smod.c:54