ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
patch_enable_lmb.c File Reference
#include <tamtypes.h>
#include <kernel.h>
#include <iopheap.h>
#include <sifrpc.h>
#include <string.h>
#include "smem.h"
#include "smod.h"
#include "slib.h"
#include "common.h"
+ Include dependency graph for patch_enable_lmb.c:

Go to the source code of this file.

Macros

#define JAL(addr)   (0x0c000000 | (0x3ffffff & ((addr) >> 2)))
 
#define HI16(addr)   (0x3c110000 | (((addr) >> 16) & 0xffff)) /* lui $s1, HI(addr) */
 
#define LO16(addr)   (0x36310000 | ((addr) & 0xffff)) /* ori $s1, LO(addr) */
 

Functions

int sbv_patch_enable_lmb (void)
 

Variables

struct smem_buf smem_buf
 
slib_exp_lib_list_t _slib_cur_exp_lib_list
 

Detailed Description

SBV patch to enable LoadModuleBuffer() via RPC.

Definition in file patch_enable_lmb.c.

Macro Definition Documentation

◆ HI16

#define HI16 (   addr)    (0x3c110000 | (((addr) >> 16) & 0xffff)) /* lui $s1, HI(addr) */

Definition at line 35 of file patch_enable_lmb.c.

◆ JAL

#define JAL (   addr)    (0x0c000000 | (0x3ffffff & ((addr) >> 2)))

Definition at line 34 of file patch_enable_lmb.c.

◆ LO16

#define LO16 (   addr)    (0x36310000 | ((addr) & 0xffff)) /* ori $s1, LO(addr) */

Definition at line 36 of file patch_enable_lmb.c.

Function Documentation

◆ 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)
u32 SifSetDma(SifDmaTransfer_t *sdd, s32 len)
void SyncDCache(void *start, void *end)
#define ALIGNED(x)
Definition: kernel.h:50
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 slib_get_exp_lib(const char *name, slib_exp_lib_t *library)
Definition: slib.c:101
int smod_get_mod_by_name(const char *name, smod_mod_info_t *info)
Definition: smod.c:54
void * dest
Definition: sifdma.h:55
void * src
Definition: sifdma.h:54
void * exports[0]
Definition: slib.h:38
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
unsigned int u32
Definition: tamtypes.h:30
unsigned char u8
Definition: tamtypes.h:23

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().

Variable Documentation

◆ _slib_cur_exp_lib_list

slib_exp_lib_list_t _slib_cur_exp_lib_list
extern

Definition at line 26 of file slib.c.

Referenced by sbv_patch_enable_lmb(), slib_exp_lib_list(), and slib_get_exp_lib().

◆ smem_buf

struct smem_buf smem_buf
extern

Definition at line 1 of file common.c.