PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
SifIopRebootBuffer.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Licenced under Academic Free License version 2.0
7# Review ps2sdk README & LICENSE files for further details.
8*/
9
15#include "kernel.h"
16#include "iopcontrol.h"
17#include "iopcontrol_special.h"
18#include "loadfile.h"
19#include "iopheap.h"
20#include "sifdma.h"
21#include "sifrpc.h"
22#include "string.h"
23#include "sbv_patches.h"
24
25#define IMGDRV_IRX_SIZE ((size__imgdrv_irx + 15) & ~15) // Was a hardcoded value of 0x400 bytes
26#define IOPBTCONF_IOP_MAX_SIZE 0x400
27
28extern int _iop_reboot_count;
29
30extern u8 iopbtconf_img[IOPBTCONF_IOP_MAX_SIZE];
31extern unsigned char _imgdrv_irx[];
32extern unsigned int size__imgdrv_irx;
33
34extern int imgdrv_offset_ioprpimg;
35extern int imgdrv_offset_ioprpsiz;
36
37extern void init_imgdrv_offsets(void);
38
39#ifdef F__iopcontrol_special_internals
40u8 iopbtconf_img[IOPBTCONF_IOP_MAX_SIZE] __attribute__((aligned(64)));
41int imgdrv_offset_ioprpimg = 0;
42int imgdrv_offset_ioprpsiz = 0;
43
44void init_imgdrv_offsets(void)
45{
46 if (imgdrv_offset_ioprpimg == 0 || imgdrv_offset_ioprpsiz == 0) {
47 int i;
48
49 for (i = 0; (unsigned int)i < size__imgdrv_irx; i += 4) {
50 if (*(u32 *)((&((unsigned char *)_imgdrv_irx)[i])) == 0xDEC1DEC1) {
51 imgdrv_offset_ioprpimg = i;
52 }
53 if (*(u32 *)((&((unsigned char *)_imgdrv_irx)[i])) == 0xDEC2DEC2) {
54 imgdrv_offset_ioprpsiz = i;
55 }
56 }
57 }
58}
59#endif
60
61// Our LOADFILE functions are slightly different.
62#define SifLoadModuleSpecial(path, arg_len, args, dontwait) \
63 _SifLoadModule(path, arg_len, args, NULL, LF_F_MOD_LOAD, dontwait);
64
65#define SifLoadModuleEncryptedSpecial(path, arg_len, args, dontwait) \
66 _SifLoadModule(path, arg_len, args, NULL, LF_F_MG_MOD_LOAD, dontwait);
67
68#ifdef F_SifIopRebootBufferEncrypted
69int SifIopRebootBufferEncrypted(const void *udnl, int size)
70{
71 int iopbtconf_img_size;
72 void *imgdrv_iop, *udnl_iop, *iopbtconf_img_iop;
73 int *imgdrv_img_size;
74 void **imgdrv_img;
75 SifDmaTransfer_t dmat[3];
76
77 sceSifInitRpc(0);
78 sceSifExitRpc();
79
80 SifIopReset("", 0);
81 while (!SifIopSync()) {};
82
84 SifInitIopHeap();
85
86 imgdrv_iop = SifAllocIopHeap(IMGDRV_IRX_SIZE);
87 udnl_iop = SifAllocIopHeap(size);
88 iopbtconf_img_iop = SifAllocIopHeap(IOPBTCONF_IOP_MAX_SIZE);
89
90 if (imgdrv_iop == NULL || udnl_iop == NULL || iopbtconf_img_iop == NULL)
91 return -1;
92
93 iopbtconf_img_size = 0; // No support for IOPBTCONF manipulation
94
95 init_imgdrv_offsets();
96 imgdrv_img = (void **)&_imgdrv_irx[imgdrv_offset_ioprpimg];
97 imgdrv_img_size = (int *)&_imgdrv_irx[imgdrv_offset_ioprpsiz];
98 dmat[0].src = _imgdrv_irx;
99 dmat[0].dest = imgdrv_iop;
100 dmat[0].size = IMGDRV_IRX_SIZE;
101 dmat[0].attr = 0;
102 dmat[1].src = (void *)udnl;
103 dmat[1].dest = udnl_iop;
104 dmat[1].size = size;
105 dmat[1].attr = 0;
106 dmat[2].src = iopbtconf_img;
107 dmat[2].dest = iopbtconf_img_iop;
108 dmat[2].size = iopbtconf_img_size;
109 dmat[2].attr = 0;
110 imgdrv_img[0] = udnl_iop;
111 imgdrv_img[1] = iopbtconf_img_iop;
112 imgdrv_img_size[0] = size;
113 imgdrv_img_size[1] = iopbtconf_img_size;
114 FlushCache(0);
115 sceSifSetDma(dmat, 3);
116
118
119 SifLoadModule("rom0:SYSCLIB", 0, NULL);
120 SifLoadModuleBuffer(imgdrv_iop, 0, NULL);
121 SifLoadModuleEncryptedSpecial("img0:", 0, NULL, 1);
122
123 sceSifExitRpc();
125
126 sceSifSetReg(SIF_REG_SMFLAG, SIF_STAT_SIFINIT);
127 sceSifSetReg(SIF_REG_SMFLAG, SIF_STAT_CMDINIT);
128 sceSifSetReg(SIF_REG_SMFLAG, SIF_STAT_BOOTEND);
129 sceSifSetReg(SIF_SYSREG_RPCINIT, 0);
130 sceSifSetReg(SIF_SYSREG_SUBADDR, 0);
131
132 _iop_reboot_count++; // Not originally here: increment to allow RPC clients to detect unbinding.
133
134 return 1;
135}
136#endif
137
138#ifdef F_SifIopRebootBuffer
139static int generateIOPBTCONF_img(void *output, const void *ioprp);
140
141int SifIopRebootBuffer(const void *ioprp, int size)
142{
143 int iopbtconf_img_size;
144 void *imgdrv_iop, *ioprp_iop, *iopbtconf_img_iop;
145 int *imgdrv_img_size;
146 void **imgdrv_img;
147 SifDmaTransfer_t dmat[3];
148
149 sceSifInitRpc(0);
150 sceSifExitRpc();
151
152 SifIopReset("", 0);
153 while (!SifIopSync()) {};
154
156 SifInitIopHeap();
157
158 imgdrv_iop = SifAllocIopHeap(IMGDRV_IRX_SIZE);
159 ioprp_iop = SifAllocIopHeap(size);
160 iopbtconf_img_iop = SifAllocIopHeap(IOPBTCONF_IOP_MAX_SIZE);
161
162 if (imgdrv_iop == NULL || ioprp_iop == NULL || iopbtconf_img_iop == NULL)
163 return -1;
164
165 iopbtconf_img_size = generateIOPBTCONF_img(iopbtconf_img, ioprp);
166
167 init_imgdrv_offsets();
168 imgdrv_img = (void **)&_imgdrv_irx[imgdrv_offset_ioprpimg];
169 imgdrv_img_size = (int *)&_imgdrv_irx[imgdrv_offset_ioprpsiz];
170 dmat[0].src = _imgdrv_irx;
171 dmat[0].dest = imgdrv_iop;
172 dmat[0].size = IMGDRV_IRX_SIZE;
173 dmat[0].attr = 0;
174 dmat[1].src = (void *)ioprp;
175 dmat[1].dest = ioprp_iop;
176 dmat[1].size = size;
177 dmat[1].attr = 0;
178 dmat[2].src = iopbtconf_img;
179 dmat[2].dest = iopbtconf_img_iop;
180 dmat[2].size = iopbtconf_img_size;
181 dmat[2].attr = 0;
182 imgdrv_img[0] = ioprp_iop;
183 imgdrv_img[1] = iopbtconf_img_iop;
184 imgdrv_img_size[0] = size;
185 imgdrv_img_size[1] = iopbtconf_img_size;
186 FlushCache(0);
187 sceSifSetDma(dmat, 3);
188
190
191 SifLoadModule("rom0:SYSCLIB", 0, NULL);
192 SifLoadModuleBuffer(imgdrv_iop, 0, NULL);
193 SifLoadModuleSpecial("rom0:UDNL", 11, "img0:\0img1:", 1);
194
195 sceSifExitRpc();
197
198 sceSifSetReg(SIF_REG_SMFLAG, SIF_STAT_SIFINIT);
199 sceSifSetReg(SIF_REG_SMFLAG, SIF_STAT_CMDINIT);
200 sceSifSetReg(SIF_REG_SMFLAG, SIF_STAT_BOOTEND);
201 sceSifSetReg(SIF_SYSREG_RPCINIT, 0);
202 sceSifSetReg(SIF_SYSREG_SUBADDR, 0);
203
204 _iop_reboot_count++; // Not originally here: increment to allow RPC clients to detect unbinding.
205
206 return 1;
207}
208
209typedef struct romdir
210{
211 char name[10];
212 u16 ExtInfoEntrySize;
213 u32 size;
214} romdir_t;
215
216typedef struct extinfo
217{
218 u16 value; /* Only applicable for the version field type. */
219 u8 ExtLength; /* The length of data appended to the end of this entry. */
220 u8 type;
221} extinfo_t;
222
223enum EXTINFO_TYPE {
224 EXTINFO_TYPE_DATE = 1,
225 EXTINFO_TYPE_VERSION,
226 EXTINFO_TYPE_COMMENT,
227 EXTINFO_TYPE_FIXED = 0x7F // Must exist at a fixed location.
228};
229
230struct iopbtconf_img
231{
232 romdir_t romdir[5];
233 u32 extinfo[4];
234};
235
236static const struct iopbtconf_img iopbtconf_img_base = {
237 {{"RESET", 8, 0},
238 {"ROMDIR", 0, 0x50},
239 {"EXTINFO", 0, 0x10},
240 {"IOPBTCONF", 8, -1},
241 {"", 0, 0}},
242 {
243 0x01040000, // EXTINFO {0x0000, 4, EXTINFO_TYPE_DATE},
244 0x20010406, // Date: 2001/04/06
245 0x01040000, // EXTINFO {0x0000, 4, EXTINFO_TYPE_DATE},
246 0x20010406, // Date: 2001/04/06
247 }};
248
249/* Generate an IOPRP image that contains IOPBTCONF, if the original contains IOPBTCONF.
250 This is required because UDNL will only seach succeeding IOPRP images for modules specified within IOPBTCONF. */
251static int generateIOPBTCONF_img(void *output, const void *ioprp)
252{
253 int size, offset, fsize_rounded;
254 romdir_t *romdir;
255 const u8 *ptr_in;
256 u8 *ptr_out;
257
258 romdir = (romdir_t *)ioprp;
259 if (strcmp(romdir[0].name, "RESET") || strcmp(romdir[1].name, "ROMDIR"))
260 return -1;
261
262 // Now locate IOPBTCONF
263 size = 0;
264 offset = 0;
265 for (; romdir->name[0] != '\0'; romdir++, offset += fsize_rounded) {
266 fsize_rounded = (romdir->size + 15) & ~15;
267 if (strcmp(romdir->name, "IOPBTCONF") == 0) {
268 romdir->name[0] = 'X'; // Change 'IOPBTCONF' to 'XOPBTCONF', so that UDNL will not find the original.
269 // Copy IOPBTCONF into the new image.
270 size = romdir->size + sizeof(iopbtconf_img_base);
271 ptr_out = (u8 *)output;
272 ptr_in = (const u8 *)ioprp;
273 memcpy(ptr_out, &iopbtconf_img_base, sizeof(iopbtconf_img_base));
274 memcpy(ptr_out + sizeof(iopbtconf_img_base), &ptr_in[offset], romdir->size);
275 ((romdir_t *)ptr_out)[3].size = romdir->size; // Update the size of IOPBTCONF within the generated IOPRP image.
276 break;
277 }
278 }
279
280 return size;
281}
282#endif
int SifLoadModule(const char *path, int arg_len, const char *args)
void SifLoadFileExit(void)
int SifLoadFileInit(void)
int SifLoadModuleBuffer(void *ptr, int arg_len, const char *args)
int SifIopReset(const char *arg, int mode)
int SifIopSync(void)
int SifIopRebootBuffer(const void *ioprp, int size)
int SifIopRebootBufferEncrypted(const void *udnl, int size)
typedef __attribute__
Definition tlbfunc.c:60
int sbv_patch_enable_lmb(void)
#define SIF_STAT_CMDINIT
Definition sifdma.h:48
#define SIF_STAT_BOOTEND
Definition sifdma.h:50
@ SIF_REG_SMFLAG
Definition sifdma.h:36
#define SIF_STAT_SIFINIT
Definition sifdma.h:46