PS2SDK
PS2 Homebrew Libraries
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
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
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];
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;
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(SifRpcGetOtherData(&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 SifSetDma(&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}
int sbv_patch_enable_lmb(void)
int slib_get_exp_lib(const char *name, slib_exp_lib_t *library)
Definition slib.c:103
int smod_get_mod_by_name(const char *name, smod_mod_info_t *info)
Definition smod.c:54