PS2SDK
PS2 Homebrew Libraries
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 
34 iomanX_iop_device_t **dev_list;
35 extern iomanX_iop_file_t file_table[MAX_FILES];
36 
37 static const char *ioman_modname = "IO/File_Manager";
38 
39 static 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 
57 static 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 
72 void 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 
93 static u32 *ioman_exports;
94 
95 #ifndef FULL_IOMAN
96 static u32 Addr_IOMAN_AddDrv = 0;
97 static u32 Addr_IOMAN_DelDrv = 0;
98 #endif
99 
100 #ifndef FULL_IOMAN
101 
102 /* This is called by a module wanting to add a device to legacy ioman. */
103 static int sbv_AddDrv(iomanX_iop_device_t *device)
104 {
105  int res;
106 
107  /* We get first dibs! */
108  res = AddDrv(device);
109 
110  if (Addr_IOMAN_AddDrv)
111  return(((int (*)(iomanX_iop_device_t *device)) (Addr_IOMAN_AddDrv))(device));
112 
113  return res;
114 }
115 
116 /* This is called by a module wanting to delete a device from legacy ioman. */
117 static int sbv_DelDrv(const char *name)
118 {
119  int res;
120 
121  res = DelDrv(name);
122 
123  if (Addr_IOMAN_DelDrv)
124  return(((int (*)(const char *name)) (Addr_IOMAN_DelDrv))(name));
125 
126  return res;
127 }
128 #endif
129 
130 #ifdef FULL_IOMAN
131 
132 // legacy ioman open and mkdir calls do not specify
133 // the "mode" arg. use default of 0644 for open and 0755 for mkdir.
134 
135 int ioman_open(const char *name, u32 flags)
136 {
137  return(iomanX_open(name, flags, 0644));
138 }
139 
140 int ioman_mkdir(const char *name)
141 {
142  return(iomanX_mkdir(name, 0755));
143 }
144 
145 // legacy format only takes one arg
146 int ioman_format(const char *dev)
147 {
148  return(iomanX_format(dev, NULL, NULL, 0));
149 }
150 
151 iomanX_iop_file_t *get_file(int fd);
152 
153 int mode2modex(int mode);
154 int modex2mode(int mode);
155 
156 static void statx2stat(iox_stat_t *iox_stat, io_stat_t* stat)
157 {
158  stat->mode = modex2mode(iox_stat->mode);
159  stat->attr = iox_stat->attr;
160  stat->size = iox_stat->size;
161  memcpy(stat->ctime, iox_stat->ctime, sizeof(iox_stat->ctime));
162  memcpy(stat->atime, iox_stat->atime, sizeof(iox_stat->atime));
163  memcpy(stat->mtime, iox_stat->mtime, sizeof(iox_stat->mtime));
164  stat->hisize = iox_stat->hisize;
165 }
166 
167 static void stat2statx(io_stat_t* stat, iox_stat_t *iox_stat)
168 {
169  iox_stat->mode = mode2modex(stat->mode);
170  iox_stat->attr = stat->attr;
171  iox_stat->size = stat->size;
172  memcpy(iox_stat->ctime, stat->ctime, sizeof(stat->ctime));
173  memcpy(iox_stat->atime, stat->atime, sizeof(stat->atime));
174  memcpy(iox_stat->mtime, stat->mtime, sizeof(stat->mtime));
175  iox_stat->hisize = stat->hisize;
176 }
177 
178 int ioman_dread(int fd, io_dirent_t *io_dirent)
179 {
180  iomanX_iop_file_t *f = get_file(fd);
181  int res;
182 
183  if (f == NULL || !(f->mode & 8))
184  return -EBADF;
185 
186  /* If this is a new device (such as pfs:) then we need to convert the mode
187  variable of the stat structure to ioman's format. */
188  if ((f->device->type & 0xf0000000) == IOP_DT_FSEXT)
189  {
190  iox_dirent_t iox_dirent;
191  res = f->device->ops->dread(f, &iox_dirent);
192 
193  statx2stat(&iox_dirent.stat, &io_dirent->stat);
194 
195  strncpy(io_dirent->name, iox_dirent.name, sizeof(iox_dirent.name));
196  }
197  else
198  {
199  typedef int io_dread_t(iomanX_iop_file_t *, io_dirent_t *);
200  io_dread_t *io_dread = (io_dread_t*) f->device->ops->dread;
201  res = io_dread(f, io_dirent);
202  }
203 
204  return res;
205 }
206 
207 int ioman_getstat(const char *name, io_stat_t *stat)
208 {
209  iox_stat_t iox_stat;
210  int res = iomanX_getstat(name, &iox_stat);
211  if (res == 0)
212  statx2stat(&iox_stat, stat);
213  return res;
214 }
215 
216 int ioman_chstat(const char *name, io_stat_t *stat, unsigned int mask)
217 {
218  iox_stat_t iox_stat;
219  stat2statx(stat, &iox_stat);
220  return iomanX_chstat(name, &iox_stat, mask);
221 }
222 
223 #endif
224 
225 extern struct irx_export_table _exp_ioman;
226 
227 int hook_ioman(void)
228 {
229  iop_library_t ioman_library = { NULL, NULL, 0x102, 0, "ioman\0\0" };
231 
232  /* If we already hooked, don't hook again */
233  if (ioman_exports)
234  return -1;
235 
236  /* Query if ioman libary exists, otherwise register our own */
237  /* By having a higher version, libraries will relink to the new entry table in RegisterLibraryEntries. */
238  if (!smod_get_mod_by_name(ioman_modname, &info) || !(ioman_exports = (u32 *)QueryLibraryEntryTable(&ioman_library)))
239  {
240  int ret;
241  u16 old_version;
242 
243  old_version = _exp_ioman.version;
244  _exp_ioman.version |= 0xFF;
245  ret = RegisterLibraryEntries(&_exp_ioman);
246  _exp_ioman.version = old_version;
247  return ret;
248  }
249 
250  // patch the IOMAN export library table to call iomanX functions
251 #ifdef FULL_IOMAN
252  /* Replace ioman library entries with our updated ones. */
253  /* By having a higher version, libraries will relink to the new entry table in RegisterLibraryEntries. */
254  {
255  int ret;
256  u16 old_version;
257 
258  old_version = _exp_ioman.version;
259  _exp_ioman.version |= 0xFF;
260  ret = RegisterLibraryEntries(&_exp_ioman);
261  _exp_ioman.version = old_version;
262  if ( ret )
263  return ret;
264  }
265  /* Prepare the old table for restoration inside unhook_ioman. */
266  ReleaseLibraryEntries((struct irx_export_table *) (((uiptr) ioman_exports) - 0x14));
267 #else
268  /* Preserve ioman's library exports. */
269  Addr_IOMAN_AddDrv = ioman_exports[20];
270  Addr_IOMAN_DelDrv = ioman_exports[21];
271 
272  ioman_exports[20] = (u32) sbv_AddDrv;
273  ioman_exports[21] = (u32) sbv_DelDrv;
274 
275  /* repair all the tables that import the ioman library */
276  fix_imports((iop_library_t *)(((uiptr) ioman_exports) - 0x14));
277 #endif
278 
279  dev_list = iomanX_GetDeviceList();
280  /* steal the original IOMAN's 16 registered device entries */
281  memcpy(dev_list, (void *) (info.text_start + info.text_size + info.data_size + 0x10), sizeof(iomanX_iop_device_t *) * 16);
282 #ifdef FULL_IOMAN
283  /* ... and clear the original so they don't get double-deinitialized */
284  memset((void *) (info.text_start + info.text_size + info.data_size + 0x10), 0, sizeof(iomanX_iop_device_t *) * 16);
285 #endif
286 
287  /* steal the original IOMAN's 16 file descriptors */
288  memcpy(file_table, (void *) (info.text_start + info.text_size + info.data_size + 0x50), sizeof(iomanX_iop_file_t) * 16);
289 #ifdef FULL_IOMAN
290  /* ... and clear the original so they don't get double-deinitialized */
291  memset((void *) (info.text_start + info.text_size + info.data_size + 0x50), 0, sizeof(iomanX_iop_file_t) * 16);
292 #endif
293 
294  return 0;
295 }
296 
297 int unhook_ioman(void)
298 {
299 #ifdef FULL_IOMAN
300  if (ioman_exports)
301  {
302  ReleaseLibraryEntries(&_exp_ioman);
303  RegisterLibraryEntries((struct irx_export_table *) (((uiptr) ioman_exports) - 0x14));
304  }
305 #else
306  if (!ioman_exports)
307  return -2;
308  /* Restore ioman's library exports. */
309  ioman_exports[20] = Addr_IOMAN_AddDrv;
310  ioman_exports[21] = Addr_IOMAN_DelDrv;
311 
312  // repair all the tables that import the ioman library
313  fix_imports((iop_library_t *) (((uiptr) ioman_exports) - 0x14));
314 #endif
315  ioman_exports = NULL;
316 
317  return 0;
318 }
319 #endif
iomanX.h
_iomanX_iop_file::device
struct _iomanX_iop_device * device
Definition: iomanX.h:76
iox_stat_t
Definition: iox_stat.h:92
IOP_DT_FSEXT
#define IOP_DT_FSEXT
Definition: iomanX.h:66
_iomanX_iop_file
Definition: iomanX.h:70
sysclib.h
smod_get_mod_by_name
int smod_get_mod_by_name(const char *name, smod_mod_info_t *info)
Definition: smod.c:54
s_info
Definition: xprintf.c:78
loadcore.h
_iop_library
Definition: loadcore.h:68
_iomanX_iop_file::mode
int mode
Definition: iomanX.h:72
irx_export_table
Definition: irx.h:90
_iomanX_iop_device
Definition: iomanX.h:81
io_stat_t
Definition: io_common.h:47
EBADF
#define EBADF
Definition: errno.h:37
iox_dirent_t
Definition: iox_stat.h:111
io_dirent_t
Definition: io_common.h:58
iomanX_format
int iomanX_format(const char *dev, const char *blockdev, void *arg, int arglen)
Definition: iomanX.c:710
defs.h
irx_import_table
Definition: irx.h:42
_ModuleInfo
Definition: loadcore.h:31
irx_import_stub
Definition: irx.h:52
tag_LC_internals::image_info
ModuleInfo_t * image_info
Definition: loadcore.h:82
errno.h
smod_get_next_mod
int smod_get_next_mod(smod_mod_info_t *cur_mod, smod_mod_info_t *next_mod)
Definition: smod.c:30