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