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 
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;
77  u32 result, *data;
78  SifDmaTransfer_t dmat;
79 
80  memset(&_slib_cur_exp_lib_list, 0, sizeof(slib_exp_lib_list_t));
81 
82  /* Locate the modload export library - it must have at least 16 exports. */
83  if (slib_get_exp_lib("modload", modload_lib) < 16)
84  return -1;
85 
86  pStartModule = modload_lib->exports[8];
87  pLoadModuleBuffer = modload_lib->exports[10];
88 
89  /* Now we need to find the loadfile module. */
90  if (!(smod_get_mod_by_name("LoadModuleByEE", &loadfile_info)))
91  return -1;
92 
93  /* In the Sony original, the whole text section of LOADFILE is scanned for the pattern.
94 
95  But that required a larger portion of EE RAM, which means that memory
96  will have to be allocated. It will also mean that this library will become dependent on additional memory (i.e. 0x01e00000-0x01e80000).
97  I think that it's fine to hardcode the address because the affected LOADFILE module is the same in all boot ROMs.
98  If someday, somebody finds an unusual (perhaps even prototype) PlayStation 2 console that has an older LOADFILE module that needs this patch too,
99  this patch can be revised.
100 
101  The original sbv library's LMB patch starts scanning at offset 0x400, in a mere 256-byte radius.
102  Locate the loadfile RPC dispatch code, where the first 4 instructions look like:
103 
104  27bdffe8 addiu $sp, -24
105  2c820006 sltiu $v0, $a0, 6
106  14400003 bnez $v0, +12
107  afbf0010 sw $ra, 0x10($sp) */
108 
109  if(loadfile_info.text_size < 0x4c4 + 128)
110  return -1;
111 
112  lf_rpc_dispatch = (void *)(loadfile_info.text_start + 0x4c4);
113  SyncDCache(&smem_buf, smem_buf.bytes+128);
114  if(sceSifGetOtherData(&RData, (void*)lf_rpc_dispatch, &smem_buf, 128, 0)>=0){
115  data=smem_buf.words;
116  if(data[0]==0x27bdffe8 && data[1]==0x2c820006 && data[2]==0x14400003 && data[3]==0xafbf0010 && data[5]==0x00001021 && data[6]==0x00041080){
117  void *lf_jump_table_end, *lf_fno_check;
118  unsigned short int JumpTableOffset_hi, JumpTableOffset_lo;
119 
120  lf_fno_check = (void*)((u8 *)lf_rpc_dispatch+4);
121 
122  /* We need to extract the address of the jump table. */
123  JumpTableOffset_hi=*(unsigned short int*)&data[7];
124  JumpTableOffset_lo=*(unsigned short int*)&data[9];
125 
126  lf_jump_table_end = (void*)((JumpTableOffset_hi<<16) + (short int)JumpTableOffset_lo + 0x18);
127 
128  /* Now we can patch our subversive LoadModuleBuffer RPC call. */
129  SifInitIopHeap();
130  if ((patch_addr = SifAllocIopHeap(sizeof lmb_patch)) == NULL)
131  return -1;
132 
133  /* result is where the RPC return structure is stored. */
134  result = (u32)patch_addr + 96;
135  lmb_patch[5] = JAL((u32)pLoadModuleBuffer);
136  lmb_patch[7] = HI16(result);
137  lmb_patch[9] = LO16(result);
138  lmb_patch[15] = JAL((u32)pStartModule);
139 
140  SyncDCache(lmb_patch, (void *)(lmb_patch + 24));
141 
142  dmat.src=lmb_patch;
143  dmat.size=sizeof(lmb_patch);
144  dmat.dest=patch_addr;
145  dmat.attr=0;
146 
147  sceSifSetDma(&dmat, 1);
148 
149  /* Finally. The last thing to do is to patch the loadfile RPC dispatch routine
150  so that it will jump to entry #6 in it's jump table, and to patch the jump
151  table itself. */
152  smem_write_word(lf_jump_table_end, (u32)patch_addr);
153  smem_write_word(lf_fno_check, 0x2C820007); //sltiu v0, a0, $0007
154 
155  return 0;
156  }
157  }
158 
159  return 1;
160 }
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:38
smem_buf
Definition: common.h:3