PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
romdrv.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <errno.h>
12#include <intrman.h>
13#include <ioman.h>
14#include <loadcore.h>
15#include <sysclib.h>
16#include <irx.h>
17
18#include "romdrv.h"
19
20IRX_ID("ROM_file_driver", 2, 1);
21
22extern struct irx_export_table _exp_romdrv;
23extern struct irx_export_table _exp_romdrvX;
24
25// Unlike the version used in UDNL, this is only 12-bytes (no padding field).
27{
28 const struct RomDirEntry *romdirent;
29 const void *data;
30 const void *extinfo;
31};
32
34{
35 int slotNum;
36 int offset;
37};
38
39static struct RomImg images[ROMDRV_MAX_IMAGES];
40static struct RomdirFileStat fileStats[ROMDRV_MAX_FILES];
41static struct RomFileSlot fileSlots[ROMDRV_MAX_FILES];
42
43/* Function prototypes */
44static int init(void);
45static int romOpen(iop_file_t *fd, const char *path, int mode);
46static int romClose(iop_file_t *);
47static int romRead(iop_file_t *fd, void *buffer, int size);
48static int romLseek(iop_file_t *fd, int offset, int whence);
49static struct RomImg *romGetImageStat(const void *start, const void *end, struct RomImg *ImageStat);
50static struct RomdirFileStat *GetFileStatFromImage(const struct RomImg *ImageStat, const char *filename, struct RomdirFileStat *stat);
51
52IOMAN_RETURN_VALUE_IMPL(0);
53IOMAN_RETURN_VALUE_IMPL(EIO);
54
55static iop_device_ops_t ops = {
56 IOMAN_RETURN_VALUE(0), // init
57 IOMAN_RETURN_VALUE(0), // deinit
58 IOMAN_RETURN_VALUE(0), // format
59 &romOpen, // open
60 &romClose, // close
61 &romRead, // read
62 IOMAN_RETURN_VALUE(EIO), // write
63 &romLseek, // lseek
64 IOMAN_RETURN_VALUE(0), // ioctl
65 IOMAN_RETURN_VALUE(0), // remove
66 IOMAN_RETURN_VALUE(0), // mkdir
67 IOMAN_RETURN_VALUE(0), // rmdir
68 IOMAN_RETURN_VALUE(0), // dopen
69 IOMAN_RETURN_VALUE(0), // dclose
70 IOMAN_RETURN_VALUE(0), // dread
71 IOMAN_RETURN_VALUE(0), // getstat
72 IOMAN_RETURN_VALUE(0), // chstat
73};
74
75static iop_device_t DeviceOps = {
76 "rom",
77 IOP_DT_FS,
78 1,
79 "ROM/Flash",
80 &ops};
81
82int _start(int argc, char **argv)
83{
84 (void)argc;
85 (void)argv;
86
87 if (RegisterLibraryEntries(&_exp_romdrv) != 0) {
88 return MODULE_NO_RESIDENT_END;
89 }
90
91#ifdef ROMDRV_EXPORT_DEVICES
92 if (RegisterLibraryEntries(&_exp_romdrvX) != 0) {
93 return MODULE_NO_RESIDENT_END;
94 }
95#endif
96
97 init();
98
99 DelDrv(DeviceOps.name);
100
101 return (AddDrv(&DeviceOps) < 0) ? MODULE_NO_RESIDENT_END : MODULE_RESIDENT_END;
102}
103
104static int init(void)
105{
106 memset(images, 0, sizeof(images));
107 memset(fileStats, 0, sizeof(fileStats));
108 memset(fileSlots, 0, sizeof(fileSlots));
109 // Add DEV2 (Boot ROM) as rom0. Unlike ROMDRV v1.1, the code for DEV1 is in the ADDDRV module.
110 romGetImageStat((const void *)0xbfc00000, (const void *)0xbfc40000, &images[0]);
111 return 0;
112}
113
114int romAddDevice(int unit, const void *image)
115{
116 int result, OldState;
117 struct RomImg *stat;
118
119 if (unit < ROMDRV_MAX_IMAGES) {
120 CpuSuspendIntr(&OldState);
121
122 if (images[unit].ImageStart == NULL) {
123 stat = romGetImageStat(image, (const void *)((const u8 *)image + 0x8000), &images[unit]);
124 CpuResumeIntr(OldState);
125
126 result = stat != NULL ? 0 : ROMDRV_ADD_BAD_IMAGE;
127 } else {
128 result = ROMDRV_ADD_FAILED;
129 CpuResumeIntr(OldState);
130 }
131 } else {
132 result = ROMDRV_ADD_FAILED;
133 }
134
135 return result;
136}
137
138int romDelDevice(int unit)
139{
140 int result, OldState;
141
142 if (unit < ROMDRV_MAX_IMAGES) {
143 CpuSuspendIntr(&OldState);
144
145 if (images[unit].ImageStart != NULL) {
146 images[unit].ImageStart = 0;
147 CpuResumeIntr(OldState);
148 result = 0;
149 } else {
150 CpuResumeIntr(OldState);
151 result = ROMDRV_DEL_FAILED;
152 }
153 } else {
154 result = ROMDRV_DEL_FAILED;
155 }
156
157 return result;
158}
159
160static int romOpen(iop_file_t *fd, const char *path, int mode)
161{
162 int OldState;
163
164 if (fd->unit < ROMDRV_MAX_IMAGES) {
165 struct RomImg *image;
166
167 image = &images[fd->unit];
168
169 if (image->ImageStart != NULL) {
170 int slotNum, result;
171 struct RomdirFileStat *stat;
172
173 if (mode != O_RDONLY) {
174 return -EACCES;
175 }
176
177 CpuSuspendIntr(&OldState);
178
179 // Locate a free file slot.
180 for (slotNum = 0; slotNum < ROMDRV_MAX_FILES; slotNum++) {
181 if (fileStats[slotNum].data == NULL) {
182 break;
183 }
184 }
185 if (slotNum == ROMDRV_MAX_FILES) {
186 CpuResumeIntr(OldState);
187 return -ENOMEM;
188 }
189
190 stat = GetFileStatFromImage(image, path, &fileStats[slotNum]);
191 CpuResumeIntr(OldState);
192
193 if (stat != NULL) {
194 result = 0;
195 fileSlots[slotNum].slotNum = slotNum;
196 fileSlots[slotNum].offset = 0;
197 fd->privdata = &fileSlots[slotNum];
198 } else {
199 result = -ENOENT;
200 }
201
202 return result;
203 } else {
204 return -ENXIO;
205 }
206 } else {
207 return -ENXIO;
208 }
209}
210
211static int romClose(iop_file_t *fd)
212{
213 struct RomFileSlot *slot = (struct RomFileSlot *)fd->privdata;
214 int result;
215
216 if (slot->slotNum < ROMDRV_MAX_FILES) {
217 struct RomdirFileStat *stat;
218
219 stat = &fileStats[slot->slotNum];
220
221 if (stat->data != NULL) {
222 stat->data = NULL;
223 result = 0;
224 } else {
225 result = -EBADF;
226 }
227 } else {
228 result = -EBADF;
229 }
230
231 return result;
232}
233
234static int romRead(iop_file_t *fd, void *buffer, int size)
235{
236 struct RomFileSlot *slot = (struct RomFileSlot *)fd->privdata;
237 struct RomdirFileStat *stat;
238
239 stat = &fileStats[slot->slotNum];
240
241 // Bounds check.
242 if (stat->romdirent->size < (u32)(slot->offset + size)) {
243 size = stat->romdirent->size - slot->offset;
244 }
245
246 if (size <= 0) // Ignore 0-byte reads.
247 {
248 return 0;
249 }
250
251 memcpy(buffer, (const u8 *)stat->data + slot->offset, size);
252 slot->offset += size;
253
254 return size;
255}
256
257static int romLseek(iop_file_t *fd, int offset, int whence)
258{
259 struct RomFileSlot *slot = (struct RomFileSlot *)fd->privdata;
260 struct RomdirFileStat *stat;
261 u32 size;
262 int newOffset;
263
264 stat = &fileStats[slot->slotNum];
265 size = stat->romdirent->size;
266
267 switch (whence) {
268 case SEEK_SET:
269 newOffset = offset;
270 break;
271 case SEEK_CUR:
272 newOffset = slot->offset + offset;
273 break;
274 case SEEK_END:
275 newOffset = size + offset;
276 break;
277 default:
278 return -EINVAL;
279 }
280
281 // Update offset.
282 slot->offset = (size < (u32)newOffset) ? size : (u32)newOffset;
283
284 return slot->offset;
285}
286
287static struct RomImg *romGetImageStat(const void *start, const void *end, struct RomImg *ImageStat)
288{
289 const u32 *ptr;
290 unsigned int offset;
291 const struct RomDirEntry *file;
292 u32 size;
293
294 offset = 0;
295 file = (struct RomDirEntry *)start;
296 for (; file < (const struct RomDirEntry *)end; file++, offset += sizeof(struct RomDirEntry)) {
297 /* Check for a valid ROM filesystem (Magic: "RESET\0\0\0\0\0"). Must have the right magic and bootstrap code size (size of RESET = bootstrap code size). */
298 ptr = (u32 *)file->name;
299 if (ptr[0] == 0x45534552 && ptr[1] == 0x54 && (*(u16 *)&ptr[2] == 0) && (((file->size + 15) & ~15) == offset)) {
300 ImageStat->ImageStart = start;
301 ImageStat->RomdirStart = ptr;
302 size = file[1].size; // Get size of image from ROMDIR (after RESET).
303 ImageStat->RomdirEnd = (const void *)((const u8 *)ptr + size);
304 return ImageStat;
305 }
306 }
307
308 ImageStat->ImageStart = NULL;
309 return NULL;
310}
311
312// Similar to the function from UDNL.
313static struct RomdirFileStat *GetFileStatFromImage(const struct RomImg *ImageStat, const char *filename, struct RomdirFileStat *stat)
314{
315 unsigned int i, offset, ExtInfoOffset;
316 u8 filename_temp[12];
317 const struct RomDirEntry *RomdirEntry;
318 struct RomdirFileStat *result;
319
320 offset = 0;
321 ExtInfoOffset = 0;
322 ((u32 *)filename_temp)[0] = 0;
323 ((u32 *)filename_temp)[1] = 0;
324 ((u32 *)filename_temp)[2] = 0;
325 for (i = 0; *filename >= 0x21 && i < sizeof(filename_temp); i++) {
326 filename_temp[i] = *filename;
327 filename++;
328 }
329
330 if (ImageStat->RomdirStart != NULL) {
331 RomdirEntry = ImageStat->RomdirStart;
332
333 do { // Fast comparison of filenames.
334 if (((u32 *)filename_temp)[0] == ((u32 *)RomdirEntry->name)[0] && ((u32 *)filename_temp)[1] == ((u32 *)RomdirEntry->name)[1] && (*(u16 *)&((u32 *)filename_temp)[2] == *(u16 *)&((u32 *)RomdirEntry->name)[2])) {
335
336 stat->romdirent = RomdirEntry;
337 stat->data = ImageStat->ImageStart + offset;
338 stat->extinfo = NULL;
339
340 if (RomdirEntry->ExtInfoEntrySize != 0) { // Unlike the version within UDNL, the existence of the extinfo entry is optional.
341 stat->extinfo = (void *)((u8 *)ImageStat->RomdirEnd + ExtInfoOffset);
342 }
343
344 result = stat;
345 goto end;
346 }
347
348 offset += (RomdirEntry->size + 15) & ~15;
349 ExtInfoOffset += RomdirEntry->ExtInfoEntrySize;
350 RomdirEntry++;
351 } while (((u32 *)RomdirEntry->name)[0] != 0x00000000); // Until the terminator entry is reached.
352
353 result = NULL;
354 } else {
355 result = NULL;
356 }
357
358end:
359 return result;
360}
361
362#ifdef ROMDRV_EXPORT_DEVICES
363const struct RomImg *romGetDevice(int unit)
364{
365 int OldState;
366 const struct RomImg *result;
367
368 if (unit < ROMDRV_MAX_IMAGES) {
369 CpuSuspendIntr(&OldState);
370
371 if (images[unit].ImageStart != NULL) {
372 result = &images[unit];
373 CpuResumeIntr(OldState);
374 } else {
375 CpuResumeIntr(OldState);
376 result = NULL;
377 }
378 } else {
379 result = NULL;
380 }
381
382 return result;
383}
384#endif
#define ENOENT
Definition errno.h:23
#define ENXIO
Definition errno.h:31
#define EINVAL
Definition errno.h:63
#define ENOMEM
Definition errno.h:43
#define EIO
Definition errno.h:29
#define EACCES
Definition errno.h:45
#define EBADF
Definition errno.h:37
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
Definition romdrv.h:40