ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
patch_fileio.c File Reference
#include <tamtypes.h>
#include <kernel.h>
#include <sifrpc.h>
#include <iopheap.h>
#include <string.h>
#include "slib.h"
#include "smod.h"
#include "common.h"
+ Include dependency graph for patch_fileio.c:

Go to the source code of this file.

Macros

#define JMP(addr)   (0x08000000|(0x3ffffff&((addr)>>2)))
 
#define JAL(addr)   (0x0c000000 | (0x3ffffff & ((addr) >> 2)))
 

Functions

int sbv_patch_fileio (void)
 

Macro Definition Documentation

◆ JAL

#define JAL (   addr)    (0x0c000000 | (0x3ffffff & ((addr) >> 2)))

Definition at line 13 of file patch_fileio.c.

◆ JMP

#define JMP (   addr)    (0x08000000|(0x3ffffff&((addr)>>2)))

Definition at line 12 of file patch_fileio.c.

Function Documentation

◆ sbv_patch_fileio()

int sbv_patch_fileio ( void  )
Returns
0: success, none-zero: error

The rom0:FILEIO RPC service has several glitches, which either result in stability issues or faulty behaviour:

  1. Interrupts are not disabled when sceSifSetDma is invoked for getstat() and dread(), which could allow simultaneous access into sceSifSetDma (a critical region).
  2. The RPC dispatcher code for remove() has a missing break, resulting in mkdir() being called after remove() returns.

Definition at line 15 of file patch_fileio.c.

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;
30  SifDmaTransfer_t dmat;
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 
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 *)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 *)mod_info.text_start + 0x09cc, new_jump_op);
93  smem_write_word((void *)mod_info.text_start + 0x0a58, new_jump_op);
94 
95  return 0;
96 }
int smem_write_word(void *address, u32 value)
Definition: common.c:40
void * SifAllocIopHeap(int size)
int SifInitIopHeap(void)
u32 SifSetDma(SifDmaTransfer_t *sdd, s32 len)
#define ALIGNED(x)
Definition: kernel.h:50
#define UNCACHED_SEG(x)
Definition: kernel.h:35
#define JMP(addr)
Definition: patch_fileio.c:12
#define JAL(addr)
Definition: patch_fileio.c:13
int smod_get_mod_by_name(const char *name, smod_mod_info_t *info)
Definition: smod.c:54
void * dest
Definition: sifdma.h:55
void * src
Definition: sifdma.h:54
u16 version
Definition: smod.h:28
u32 text_start
Definition: smod.h:36
#define NULL
Definition: tamtypes.h:91
unsigned int u32
Definition: tamtypes.h:30

References ALIGNED, SifDmaTransfer_t::attr, SifDmaTransfer_t::dest, JAL, JMP, NULL, SifAllocIopHeap(), SifInitIopHeap(), SifSetDma(), SifDmaTransfer_t::size, smem_write_word(), smod_get_mod_by_name(), SifDmaTransfer_t::src, smod_mod_info_t::text_start, UNCACHED_SEG, and smod_mod_info_t::version.