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