sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
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
15
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 */
29extern struct smem_buf smem_buf;
30
31/* from slib.c */
32extern 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
38static 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}
ModuleInfo_t * smod_get_mod_by_name(const char *name)
Definition smod.c:63
int sbv_patch_enable_lmb(void)
struct _slib_exp_lib_list slib_exp_lib_list_t
int slib_get_exp_lib(const char *name, slib_exp_lib_t *library)
Definition slib.c:103
struct _slib_exp_lib slib_exp_lib_t
struct _smod_mod_info smod_mod_info_t