PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
ioman_sbv.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# Copyright (c) 2004 adresd <adresd_ps2dev@yahoo.com>
8# Licenced under Academic Free License version 2.0
9# Review ps2sdk README & LICENSE files for further details.
10*/
11
17#ifdef IOMANX_ENABLE_LEGACY_IOMAN_HOOK
18#include <stdarg.h>
19
20#include "types.h"
21#include "defs.h"
22#include "loadcore.h"
23#include "iomanX.h"
24#include "sysclib.h"
25
26#include "errno.h"
27
28// define this to hook all IOMAN exports instead of just AddDrv and DelDrv
29#define FULL_IOMAN
30
31#define MAX_DEVICES 32
32#define MAX_FILES 32
33
34iomanX_iop_device_t **dev_list;
35extern iomanX_iop_file_t file_table[MAX_FILES];
36
37static const char *ioman_modname = "IO/File_Manager";
38
39static int smod_get_next_mod(ModuleInfo_t *cur_mod, ModuleInfo_t *next_mod)
40{
41 void *addr;
42
43 /* If cur_mod is 0, return the head of the list (IOP address 0x800). */
44 if (!cur_mod) {
45 addr = GetLoadcoreInternalData()->image_info;
46 } else {
47 if (!cur_mod->next)
48 return 0;
49 else
50 addr = cur_mod->next;
51 }
52
53 memcpy(next_mod, addr, sizeof(ModuleInfo_t));
54 return next_mod->id;
55}
56
57static int smod_get_mod_by_name(const char *name, ModuleInfo_t *info)
58{
59 int len = strlen(name) + 1; /* Thanks to adresd for this fix. */
60
61 if (!smod_get_next_mod(NULL, info))
62 return 0;
63
64 do {
65 if (!memcmp(info->name, name, len))
66 return info->id;
67 } while (smod_get_next_mod(info, info) != 0);
68
69 return 0;
70}
71
72void fix_imports(iop_library_t *lib)
73{
74 struct irx_import_table *table;
75 struct irx_import_stub *stub;
76
77 FlushDcache();
78
79 // go through each table that imports the library
80 for(table = lib->caller; table != NULL; table = table->next)
81 {
82 // go through each import in the table
83 for(stub = (struct irx_import_stub *) table->stubs; stub->jump != 0; stub++)
84 {
85 // patch the stub to jump to the address specified in the library export table for "fno"
86 stub->jump = 0x08000000 | (((u32) lib->exports[stub->fno] << 4) >> 6);
87 }
88 }
89
90 FlushIcache();
91}
92
93static u32 *ioman_exports;
94
95static u32 Addr_IOMAN_open = 0;
96static u32 Addr_IOMAN_close = 0;
97static u32 Addr_IOMAN_read = 0;
98static u32 Addr_IOMAN_write = 0;
99static u32 Addr_IOMAN_lseek = 0;
100static u32 Addr_IOMAN_ioctl = 0;
101static u32 Addr_IOMAN_remove = 0;
102static u32 Addr_IOMAN_mkdir = 0;
103static u32 Addr_IOMAN_rmdir = 0;
104static u32 Addr_IOMAN_dopen = 0;
105static u32 Addr_IOMAN_dclose = 0;
106static u32 Addr_IOMAN_dread = 0;
107static u32 Addr_IOMAN_getstat = 0;
108static u32 Addr_IOMAN_chstat = 0;
109static u32 Addr_IOMAN_format = 0;
110
111static u32 Addr_IOMAN_AddDrv = 0;
112static u32 Addr_IOMAN_DelDrv = 0;
113
114#ifndef FULL_IOMAN
115
116/* This is called by a module wanting to add a device to legacy ioman. */
117static int sbv_AddDrv(iomanX_iop_device_t *device)
118{
119 int res;
120
121 /* We get first dibs! */
122 res = AddDrv(device);
123
124 if (Addr_IOMAN_AddDrv)
125 return(((int (*)(iomanX_iop_device_t *device)) (Addr_IOMAN_AddDrv))(device));
126
127 return res;
128}
129
130/* This is called by a module wanting to delete a device from legacy ioman. */
131static int sbv_DelDrv(const char *name)
132{
133 int res;
134
135 res = DelDrv(name);
136
137 if (Addr_IOMAN_DelDrv)
138 return(((int (*)(const char *)) (Addr_IOMAN_DelDrv))(name));
139
140 return res;
141}
142#endif
143
144#ifdef FULL_IOMAN
145
146// legacy ioman open and mkdir calls do not specify
147// the "mode" arg. use default of 0644 for open and 0755 for mkdir.
148
149int ioman_open(const char *name, u32 flags)
150{
151 return(iomanX_open(name, flags, 0644));
152}
153
154int ioman_mkdir(const char *name)
155{
156 return(iomanX_mkdir(name, 0755));
157}
158
159// legacy format only takes one arg
160int ioman_format(const char *dev)
161{
162 return(iomanX_format(dev, NULL, NULL, 0));
163}
164
165iomanX_iop_file_t *get_file(int fd);
166
167int mode2modex(int mode);
168int modex2mode(int mode);
169
170static void statx2stat(iox_stat_t *iox_stat, io_stat_t* stat)
171{
172 stat->mode = modex2mode(iox_stat->mode);
173 stat->attr = iox_stat->attr;
174 stat->size = iox_stat->size;
175 memcpy(stat->ctime, iox_stat->ctime, sizeof(iox_stat->ctime));
176 memcpy(stat->atime, iox_stat->atime, sizeof(iox_stat->atime));
177 memcpy(stat->mtime, iox_stat->mtime, sizeof(iox_stat->mtime));
178 stat->hisize = iox_stat->hisize;
179}
180
181static void stat2statx(io_stat_t* stat, iox_stat_t *iox_stat)
182{
183 iox_stat->mode = mode2modex(stat->mode);
184 iox_stat->attr = stat->attr;
185 iox_stat->size = stat->size;
186 memcpy(iox_stat->ctime, stat->ctime, sizeof(stat->ctime));
187 memcpy(iox_stat->atime, stat->atime, sizeof(stat->atime));
188 memcpy(iox_stat->mtime, stat->mtime, sizeof(stat->mtime));
189 iox_stat->hisize = stat->hisize;
190}
191
192int ioman_dread(int fd, io_dirent_t *io_dirent)
193{
194 iomanX_iop_file_t *f = get_file(fd);
195 int res;
196
197 if (f == NULL || !(f->mode & 8))
198 return -EBADF;
199
200 /* If this is a new device (such as pfs:) then we need to convert the mode
201 variable of the stat structure to ioman's format. */
202 if ((f->device->type & 0xf0000000) == IOP_DT_FSEXT)
203 {
204 iox_dirent_t iox_dirent;
205 res = f->device->ops->dread(f, &iox_dirent);
206
207 statx2stat(&iox_dirent.stat, &io_dirent->stat);
208
209 strncpy(io_dirent->name, iox_dirent.name, sizeof(iox_dirent.name));
210 }
211 else
212 {
213 typedef int io_dread_t(iomanX_iop_file_t *, io_dirent_t *);
214 io_dread_t *io_dread = (io_dread_t*) f->device->ops->dread;
215 res = io_dread(f, io_dirent);
216 }
217
218 return res;
219}
220
221int ioman_getstat(const char *name, io_stat_t *stat)
222{
223 iox_stat_t iox_stat;
224 int res = iomanX_getstat(name, &iox_stat);
225 if (res == 0)
226 statx2stat(&iox_stat, stat);
227 return res;
228}
229
230int ioman_chstat(const char *name, io_stat_t *stat, unsigned int mask)
231{
232 iox_stat_t iox_stat;
233 stat2statx(stat, &iox_stat);
234 return iomanX_chstat(name, &iox_stat, mask);
235}
236
237#endif
238
239int hook_ioman(void)
240{
241 iop_library_t ioman_library = { NULL, NULL, 0x102, 0, "ioman\0\0" };
243
244 dev_list = iomanX_GetDeviceList();
245
246 if (smod_get_mod_by_name(ioman_modname, &info))
247 {
248 // steal the original IOMAN's 16 registered device entries
249 memcpy(dev_list, (void *) (info.text_start + info.text_size + info.data_size + 0x10), sizeof(iomanX_iop_device_t *) * 16);
250
251 // steal the original IOMAN's 16 file descriptors
252 memcpy(file_table, (void *) (info.text_start + info.text_size + info.data_size + 0x50), sizeof(iomanX_iop_file_t) * 16);
253 }
254 else { return(-1); }
255
256 // patch the IOMAN export library table to call iomanX functions
257 if ((ioman_exports = (u32 *)QueryLibraryEntryTable(&ioman_library)) != NULL)
258 {
259 /* Preserve ioman's library exports. */
260 Addr_IOMAN_open = ioman_exports[4];
261 Addr_IOMAN_close = ioman_exports[5];
262 Addr_IOMAN_read = ioman_exports[6];
263 Addr_IOMAN_write = ioman_exports[7];
264 Addr_IOMAN_lseek = ioman_exports[8];
265 Addr_IOMAN_ioctl = ioman_exports[9];
266 Addr_IOMAN_remove = ioman_exports[10];
267 Addr_IOMAN_mkdir = ioman_exports[11];
268 Addr_IOMAN_rmdir = ioman_exports[12];
269 Addr_IOMAN_dopen = ioman_exports[13];
270 Addr_IOMAN_dclose = ioman_exports[14];
271 Addr_IOMAN_dread = ioman_exports[15];
272 Addr_IOMAN_getstat = ioman_exports[16];
273 Addr_IOMAN_chstat = ioman_exports[17];
274 Addr_IOMAN_format = ioman_exports[18];
275 Addr_IOMAN_AddDrv = ioman_exports[20];
276 Addr_IOMAN_DelDrv = ioman_exports[21];
277
278#ifdef FULL_IOMAN
279 ioman_exports[4] = (u32) ioman_open;
280 ioman_exports[5] = (u32) iomanX_close;
281 ioman_exports[6] = (u32) iomanX_read;
282 ioman_exports[7] = (u32) iomanX_write;
283 ioman_exports[8] = (u32) iomanX_lseek;
284 ioman_exports[9] = (u32) iomanX_ioctl;
285 ioman_exports[10] = (u32) iomanX_remove;
286 ioman_exports[11] = (u32) ioman_mkdir;
287 ioman_exports[12] = (u32) iomanX_rmdir;
288 ioman_exports[13] = (u32) iomanX_dopen;
289 ioman_exports[14] = (u32) iomanX_close;
290 ioman_exports[15] = (u32) ioman_dread;
291 ioman_exports[16] = (u32) ioman_getstat;
292 ioman_exports[17] = (u32) ioman_chstat;
293 ioman_exports[18] = (u32) ioman_format;
294 ioman_exports[20] = (u32) iomanX_AddDrv;
295 ioman_exports[21] = (u32) iomanX_DelDrv;
296#else
297 ioman_exports[20] = (u32) sbv_AddDrv;
298 ioman_exports[21] = (u32) sbv_DelDrv;
299#endif
300
301 // repair all the tables that import the ioman library
302 fix_imports((iop_library_t *) (((u32) ioman_exports) - 0x14));
303 }
304 else { return(-2); }
305
306 return(0);
307}
308
309int unhook_ioman()
310{
311 int i;
312
313 dev_list = iomanX_GetDeviceList();
314
315 /* Remove all registered devices. */
316 for (i = 0; i < MAX_DEVICES; i++) {
317 if (dev_list[i] != NULL) {
318 dev_list[i]->ops->deinit(dev_list[i]);
319 dev_list[i] = NULL;
320 }
321 }
322
323 /* Restore ioman's library exports. */
324 ioman_exports[4] = Addr_IOMAN_open;
325 ioman_exports[5] = Addr_IOMAN_close;
326 ioman_exports[6] = Addr_IOMAN_read;
327 ioman_exports[7] = Addr_IOMAN_write;
328 ioman_exports[8] = Addr_IOMAN_lseek;
329 ioman_exports[9] = Addr_IOMAN_ioctl;
330 ioman_exports[10] = Addr_IOMAN_remove;
331 ioman_exports[11] = Addr_IOMAN_mkdir;
332 ioman_exports[12] = Addr_IOMAN_rmdir;
333 ioman_exports[13] = Addr_IOMAN_dopen;
334 ioman_exports[14] = Addr_IOMAN_dclose;
335 ioman_exports[15] = Addr_IOMAN_dread;
336 ioman_exports[16] = Addr_IOMAN_getstat;
337 ioman_exports[17] = Addr_IOMAN_chstat;
338 ioman_exports[18] = Addr_IOMAN_format;
339
340 ioman_exports[20] = Addr_IOMAN_AddDrv;
341 ioman_exports[21] = Addr_IOMAN_DelDrv;
342
343 // repair all the tables that import the ioman library
344 fix_imports((iop_library_t *) (((u32) ioman_exports) - 0x14));
345
346 return 0;
347}
348#endif
#define EBADF
Definition errno.h:37
int iomanX_format(const char *dev, const char *blockdev, void *arg, int arglen)
Definition iomanX.c:701
struct _iomanX_iop_device * device
Definition iomanX.h:76
#define IOP_DT_FSEXT
Definition iomanX.h:66
ModuleInfo_t * image_info
Definition loadcore.h:82
int smod_get_next_mod(smod_mod_info_t *cur_mod, smod_mod_info_t *next_mod)
Definition smod.c:30
int smod_get_mod_by_name(const char *name, smod_mod_info_t *info)
Definition smod.c:54