ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
sbv_patches.h File Reference
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int sbv_patch_enable_lmb (void)
 
int sbv_patch_disable_prefix_check (void)
 
int sbv_patch_user_mem_clear (void *start)
 
int sbv_patch_fileio (void)
 

Detailed Description

SBV patches.

Definition in file sbv_patches.h.

Function Documentation

◆ sbv_patch_disable_prefix_check()

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

The MODLOAD module has a black/white (depends on version) list that determines what devices can have unprotected EE/IOP executables loaded from. Typically, only protected executables can be loaded from user-writable media like the memory card or HDD unit. This patch will disable the black/white list, allowing executables to be freely loaded from any device.

Definition at line 24 of file patch_disable_prefix_check.c.

25 {
26  union {
27  u8 buf[256];
28  slib_exp_lib_t exp_lib;
29  } buf;
30  static u32 patch[2] ALIGNED(16)={
31  0x03e00008, /* jr $ra */
32  0x00001021 /* addiu $v0, $0, 0 */
33  };
34  SifDmaTransfer_t dmat;
35  slib_exp_lib_t *modload_lib = &buf.exp_lib;
36 
37  memset(&_slib_cur_exp_lib_list, 0, sizeof(slib_exp_lib_list_t));
38 
39  if (!slib_get_exp_lib("modload", modload_lib))
40  return -1;
41 
42  dmat.src=patch;
43  dmat.size=sizeof(patch); //16-bytes will be written to IOP RAM, but the function on the IOP side is longer than 16 bytes in length.
44  dmat.dest=modload_lib->exports[15];
45  dmat.attr=0;
46 
47  SifSetDma(&dmat, 1);
48 
49  return 0;
50 }
u32 SifSetDma(SifDmaTransfer_t *sdd, s32 len)
#define ALIGNED(x)
Definition: kernel.h:50
slib_exp_lib_list_t _slib_cur_exp_lib_list
Definition: slib.c:26
int slib_get_exp_lib(const char *name, slib_exp_lib_t *library)
Definition: slib.c:101
void * dest
Definition: sifdma.h:55
void * src
Definition: sifdma.h:54
void * exports[0]
Definition: slib.h:38
unsigned int u32
Definition: tamtypes.h:30
unsigned char u8
Definition: tamtypes.h:23

References _slib_cur_exp_lib_list, ALIGNED, SifDmaTransfer_t::attr, SifDmaTransfer_t::dest, slib_exp_lib_t::exports, SifSetDma(), SifDmaTransfer_t::size, slib_get_exp_lib(), and SifDmaTransfer_t::src.

◆ sbv_patch_enable_lmb()

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

The rom0:LOADFILE RPC service is missing support for LoadModuleBuffer, making it impossible (by default) to IOP load modules from EE RAM. Newer LOADFILE modules do not have this limitation. Unlike the official patch, this version is not dependent on 0x01e00000-0x01e80000.

Definition at line 38 of file patch_enable_lmb.c.

39 {
40  /* This is the routine called by the loadfile RPC dispatcher for LoadModuleBuffer
41  over RPC (call #6). The bracketed operands are the ones patched by the real
42  locations in IOP memory before being installed onto the IOP. */
43  static u32 lmb_patch[32] ALIGNED(64) = {
44  0x27bdffd8, /* addiu $sp, -40 */
45  0xafb00018, /* sw $s0, 0x18($sp) */
46  0xafbf0020, /* sw $ra, 0x20($sp) */
47  0x00808021, /* move $s0, $a0 */
48  0x8c840000, /* lw $a0, 0($a0) */
49  0x0c000000, /* jal [LoadModuleBuffer] */
50  0xafb1001c, /* sw $s1, 0x1c($sp) */
51  0x3c110000, /* lui $s1, [HI16(result)] */
52  0x04400008, /* bltz $v0, 1f */
53  0x36310000, /* ori $s1, [LO16(result)] */
54  0x00402021, /* move $a0, $v0 */
55  0x26250008, /* addiu $a1, $s1, 8 */
56  0x8e060004, /* lw $a2, 4($s0) */
57  0x26070104, /* addiu $a3, $s0, 0x104 */
58  0x26280004, /* addiu $t0, $s1, 4 */
59  0x0c000000, /* jal [StartModule] */
60  0xafa80010, /* sw $t0, 0x10($sp) */
61  0xae220000, /* 1: sw $v0, 0($s1) */
62  0x02201021, /* move $v0, $s1 */
63  0x8fbf0020, /* lw $ra, 0x20($sp) */
64  0x8fb1001c, /* lw $s1, 0x1c($sp) */
65  0x8fb00018, /* lw $s0, 0x18($sp) */
66  0x03e00008, /* jr $ra */
67  0x27bd0028, /* addiu $sp, 40 */
68  0x00000000, 0x00000000,
69  0x7962424c, 0x00004545, /* "LBbyEE" */
70  0x00000000, 0x00000000, 0x00000000, 0x00000000
71  };
72  u8 buf[256];
73  SifRpcReceiveData_t RData;
74  slib_exp_lib_t *modload_lib = (slib_exp_lib_t *)buf;
75  smod_mod_info_t loadfile_info;
76  void *pStartModule, *pLoadModuleBuffer, *patch_addr, *lf_rpc_dispatch, *lf_jump_table_end, *lf_fno_check;
77  unsigned short int JumpTableOffset_hi, JumpTableOffset_lo;
78  u32 result, *data;
79  int id;
80  SifDmaTransfer_t dmat;
81 
82  memset(&_slib_cur_exp_lib_list, 0, sizeof(slib_exp_lib_list_t));
83 
84  /* Locate the modload export library - it must have at least 16 exports. */
85  if (slib_get_exp_lib("modload", modload_lib) < 16)
86  return -1;
87 
88  pStartModule = modload_lib->exports[8];
89  pLoadModuleBuffer = modload_lib->exports[10];
90 
91  /* Now we need to find the loadfile module. */
92  if (!(id = smod_get_mod_by_name("LoadModuleByEE", &loadfile_info)))
93  return -1;
94 
95  /* In the Sony original, the whole text section of LOADFILE is scanned for the pattern.
96 
97  But that required a larger portion of EE RAM, which means that memory
98  will have to be allocated. It will also mean that this library will become dependent on additional memory (i.e. 0x01e00000-0x01e80000).
99  I think that it's fine to hardcode the address because the affected LOADFILE module is the same in all boot ROMs.
100  If someday, somebody finds an unusual (perhaps even prototype) PlayStation 2 console that has an older LOADFILE module that needs this patch too,
101  this patch can be revised.
102 
103  The original sbv library's LMB patch starts scanning at offset 0x400, in a mere 256-byte radius.
104  Locate the loadfile RPC dispatch code, where the first 4 instructions look like:
105 
106  27bdffe8 addiu $sp, -24
107  2c820006 sltiu $v0, $a0, 6
108  14400003 bnez $v0, +12
109  afbf0010 sw $ra, 0x10($sp) */
110 
111  if(loadfile_info.text_size < 0x4c4 + 128)
112  return -1;
113 
114  lf_rpc_dispatch = (void *)(loadfile_info.text_start + 0x4c4);
116  if(SifRpcGetOtherData(&RData, (void*)lf_rpc_dispatch, &smem_buf, 128, 0)>=0){
118  if(data[0]==0x27bdffe8 && data[1]==0x2c820006 && data[2]==0x14400003 && data[3]==0xafbf0010 && data[5]==0x00001021 && data[6]==0x00041080){
119  lf_fno_check = (void*)(lf_rpc_dispatch+4);
120 
121  /* We need to extract the address of the jump table. */
122  JumpTableOffset_hi=*(unsigned short int*)&data[7];
123  JumpTableOffset_lo=*(unsigned short int*)&data[9];
124 
125  lf_jump_table_end = (void*)((JumpTableOffset_hi<<16) + (short int)JumpTableOffset_lo + 0x18);
126 
127  /* Now we can patch our subversive LoadModuleBuffer RPC call. */
128  SifInitIopHeap();
129  if ((patch_addr = SifAllocIopHeap(sizeof lmb_patch)) == NULL)
130  return -1;
131 
132  /* result is where the RPC return structure is stored. */
133  result = (u32)patch_addr + 96;
134  lmb_patch[5] = JAL((u32)pLoadModuleBuffer);
135  lmb_patch[7] = HI16(result);
136  lmb_patch[9] = LO16(result);
137  lmb_patch[15] = JAL((u32)pStartModule);
138 
139  SyncDCache(lmb_patch, (void *)(lmb_patch + 24));
140 
141  dmat.src=lmb_patch;
142  dmat.size=sizeof(lmb_patch);
143  dmat.dest=patch_addr;
144  dmat.attr=0;
145 
146  SifSetDma(&dmat, 1);
147 
148  /* Finally. The last thing to do is to patch the loadfile RPC dispatch routine
149  so that it will jump to entry #6 in it's jump table, and to patch the jump
150  table itself. */
151  smem_write_word(lf_jump_table_end, (u32)patch_addr);
152  smem_write_word(lf_fno_check, 0x2C820007); //sltiu v0, a0, $0007
153 
154  return 0;
155  }
156  }
157 
158  return 1;
159 }
int smem_write_word(void *address, u32 value)
Definition: common.c:40
void * SifAllocIopHeap(int size)
int SifInitIopHeap(void)
void SyncDCache(void *start, void *end)
u32 data
Definition: libmouse.c:36
#define HI16(addr)
slib_exp_lib_list_t _slib_cur_exp_lib_list
Definition: slib.c:26
#define LO16(addr)
#define JAL(addr)
s32 result
Definition: rpc_client.c:23
int SifRpcGetOtherData(SifRpcReceiveData_t *rd, void *src, void *dest, int size, int mode)
int smod_get_mod_by_name(const char *name, smod_mod_info_t *info)
Definition: smod.c:54
Definition: common.h:3
u8 bytes[SMEM_BUF_SIZE/sizeof(u8)]
Definition: common.h:5
u32 words[SMEM_BUF_SIZE/sizeof(u32)]
Definition: common.h:6
u32 text_start
Definition: smod.h:36
u32 text_size
Definition: smod.h:37
#define NULL
Definition: tamtypes.h:91

References _slib_cur_exp_lib_list, ALIGNED, SifDmaTransfer_t::attr, smem_buf::bytes, data, SifDmaTransfer_t::dest, slib_exp_lib_t::exports, HI16, JAL, LO16, NULL, result, SifAllocIopHeap(), SifInitIopHeap(), SifRpcGetOtherData(), SifSetDma(), SifDmaTransfer_t::size, slib_get_exp_lib(), smem_write_word(), smod_get_mod_by_name(), SifDmaTransfer_t::src, SyncDCache(), smod_mod_info_t::text_size, smod_mod_info_t::text_start, and smem_buf::words.

Referenced by main().

◆ 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 }
#define UNCACHED_SEG(x)
Definition: kernel.h:35
#define JMP(addr)
Definition: patch_fileio.c:12
#define JAL(addr)
Definition: patch_fileio.c:13
u16 version
Definition: smod.h:28

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.

◆ sbv_patch_user_mem_clear()

int sbv_patch_user_mem_clear ( void *  start)

@start address above which all user memory is cleared

Returns
0: success, -1: error

LoadExecPS2() wipes all user-space memory above 0x82000. With this patch, you can define a different start address to prevent your data from being overwritten. In order to completely disable the memory clear, simply pass 0x02000000 to it.

Definition at line 9 of file patch_user_mem_clear.c.

10 {
11  int ret = -1;
12  u32 *p;
13 
14  DI();
16 
17  for (p = (unsigned int*)0x80001000; p < (unsigned int*)0x80080000; p++) {
18  /*
19  * Search for function call and patch $a0
20  * lui $a0, 0x0008
21  * jal InitializeUserMemory
22  * ori $a0, $a0, 0x2000
23  */
24  if (p[0] == 0x3c040008 && (p[1] & 0xfc000000) == 0x0c000000 && p[2] == 0x34842000) {
25  p[0] = 0x3c040000 | ((unsigned int)start >> 16);
26  p[2] = 0x34840000 | ((unsigned int)start & 0xffff);
27  ret = 0;
28  break;
29  }
30  }
31 
32  ee_kmode_exit();
33  EI();
34 
35  return ret;
36 }
static int ee_kmode_exit()
Definition: kernel.h:198
static int ee_kmode_enter()
Definition: kernel.h:181
#define DI
Definition: kernel.h:24
#define EI
Definition: kernel.h:25

References DI, ee_kmode_enter(), ee_kmode_exit(), and EI.