3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
7 #include "include/usbld.h"
8 #include "include/util.h"
9 #include "include/pad.h"
10 #include "include/system.h"
11 #include "include/ioman.h"
14 char VMC_filename
[1024];
17 int VMC_thread_priority
;
21 extern void *genvmc_irx
;
22 extern int size_genvmc_irx
;
25 extern void *imgdrv_irx
;
26 extern int size_imgdrv_irx
;
28 extern void *eesync_irx
;
29 extern int size_eesync_irx
;
31 extern void *cdvdfsv_irx
;
32 extern int size_cdvdfsv_irx
;
34 extern void *cddev_irx
;
35 extern int size_cddev_irx
;
37 extern void *ps2dev9_irx
;
38 extern int size_ps2dev9_irx
;
40 extern void *smstcpip_irx
;
41 extern int size_smstcpip_irx
;
43 extern void *ingame_smstcpip_irx
;
44 extern int size_ingame_smstcpip_irx
;
46 extern void *smsmap_irx
;
47 extern int size_smsmap_irx
;
49 extern void *udptty_irx
;
50 extern int size_udptty_irx
;
52 extern void *ioptrap_irx
;
53 extern int size_ioptrap_irx
;
55 extern void *smbman_irx
;
56 extern int size_smbman_irx
;
58 extern void *discid_irx
;
59 extern int size_discid_irx
;
61 extern void *iomanx_irx
;
62 extern int size_iomanx_irx
;
64 extern void *filexio_irx
;
65 extern int size_filexio_irx
;
67 extern void *poweroff_irx
;
68 extern int size_poweroff_irx
;
70 extern void *ps2atad_irx
;
71 extern int size_ps2atad_irx
;
73 extern void *ps2hdd_irx
;
74 extern int size_ps2hdd_irx
;
76 extern void *hdldsvr_irx
;
77 extern int size_hdldsvr_irx
;
79 extern void *eecore_elf
;
80 extern int size_eecore_elf
;
82 extern void *alt_eecore_elf
;
83 extern int size_alt_eecore_elf
;
85 extern void *elfldr_elf
;
86 extern int size_elfldr_elf
;
88 extern void *kpatch_10K_elf
;
89 extern int size_kpatch_10K_elf
;
91 extern void *smsutils_irx
;
92 extern int size_smsutils_irx
;
94 extern void *usbd_irx
;
95 extern int size_usbd_irx
;
97 #define MAX_MODULES 32
98 static void *g_sysLoadedModBuffer
[MAX_MODULES
];
100 #define ELF_MAGIC 0x464c457f
101 #define ELF_PT_LOAD 1
104 #define CDVD_R_SCMD ((volatile u8*)0xBF402016)
105 #define CDVD_R_SDIN ((volatile u8*)0xBF402017)
108 #define DEV9_R_1460 ((volatile u16*)0xBF801460)
109 #define DEV9_R_1464 ((volatile u16*)0xBF801464)
110 #define DEV9_R_1466 ((volatile u16*)0xBF801466)
111 #define DEV9_R_146C ((volatile u16*)0xBF80146C)
112 #define DEV9_R_146E ((volatile u16*)0xBF80146E)
113 #define DEV9_R_1474 ((volatile u16*)0xBF801474)
115 #define ROMSEG0(vaddr) (0xbfc00000 | vaddr) // arghhh! avoid using this macro: some PS2 with modchips badly disabled seems
116 // to not tolerate very well direct BIOS access!!!
117 #define KSEG0(vaddr) (0x80000000 | vaddr)
118 #define JAL(addr) (0x0c000000 | ((addr & 0x03ffffff) >> 2))
121 u8 ident
[16]; // struct definition for ELF object header
138 u32 type
; // struct definition for ELF program section header
159 int sysLoadModuleBuffer(void *buffer
, int size
, int argc
, char *argv
) {
161 int i
, id
, ret
, index
= 0;
163 // check we have not reached MAX_MODULES
164 for (i
=0; i
<MAX_MODULES
; i
++) {
165 if (g_sysLoadedModBuffer
[i
] == NULL
) {
170 if (i
== MAX_MODULES
)
173 // check if the module was already loaded
174 for (i
=0; i
<MAX_MODULES
; i
++) {
175 if (g_sysLoadedModBuffer
[i
] == buffer
) {
181 id
= SifExecModuleBuffer(buffer
, size
, argc
, argv
, &ret
);
182 if ((id
< 0) || (ret
))
185 // add the module to the list
186 g_sysLoadedModBuffer
[index
] = buffer
;
191 void sysApplyFILEIOPatches(void)
193 // This patch is a fix for FILEIO on IOP:
194 // the handler of rpc_fioremove doesn't exit just after file is
195 // removed due to a bug, and chain with rpc_fiomkdir which have for
196 // effect to create a folder of the same name that the file deleted...
197 // We'll seach for FILEIO text section start and patch the rpc
198 // handler to jump to a subroutine to correct this.
199 // This subroutine is 16 bytes and written in a FILEIO string
200 // that have poor interest: "iop heap service (99/11/03)\n" will
201 // be cutted to "iop heap service"
202 // text + 0x1447: patch with 0 (1byte)
203 // text + 0x1448: patch with (16 bytes)
204 // text + 0x0bb8: patch with 0x0c000512(+text_start) (4bytes)
205 // 0x0c0001ce(+text_start) // jal fio_remove
207 // 0x0800033a(+text_start) // j rpc_handler_exit
210 smod_mod_info_t mod_info
;
212 u8 new_fioremove
[16];
213 volatile u32 j_new_fioremove
= 0x08000512;
214 volatile u32 j_rpc_handler_exit
= 0x0800033a;
215 volatile u8 string_term
= 0;
217 memset(&mod_info
, 0, sizeof(mod_info
));
219 int ret
= smod_get_mod_by_name("FILEIO_service", &mod_info
);
220 if ((!ret
) || (mod_info
.version
!= 0x101))
223 smem_read((void *)mod_info
.text_start
+ 0x0bb8, jal_fioremove
, sizeof(jal_fioremove
));
225 memset(new_fioremove
, 0, sizeof(new_fioremove
));
226 memcpy(&new_fioremove
[0], jal_fioremove
, sizeof(jal_fioremove
));
227 j_rpc_handler_exit
+= ((u32
)mod_info
.text_start
>> 2);
228 memcpy(&new_fioremove
[8], (void *)&j_rpc_handler_exit
, sizeof(j_rpc_handler_exit
));
229 smem_write((void *)mod_info
.text_start
+ 0x1447, (void *)&string_term
, sizeof(string_term
));
231 smem_write((void *)mod_info
.text_start
+ 0x1448, new_fioremove
, sizeof(new_fioremove
));
233 j_new_fioremove
+= ((u32
)mod_info
.text_start
>> 2);
234 smem_write((void *)mod_info
.text_start
+ 0x0bb8, (void *)&j_new_fioremove
, sizeof(j_new_fioremove
));
240 void sysReset(int modload_mask
) {
243 cdInit(CDVD_INIT_NOCHECK
);
244 cdInit(CDVD_INIT_EXIT
);
246 while(!SifIopReset("rom0:UDNL rom0:EELOADCNF",0));
247 while(!SifIopSync());
259 // init loadfile & iopheap services
264 sbv_patch_enable_lmb();
265 sbv_patch_disable_prefix_check();
266 sysApplyFILEIOPatches();
268 SifLoadModule("rom0:SIO2MAN", 0, NULL
);
270 if (modload_mask
& SYS_LOAD_MC_MODULES
) {
271 SifLoadModule("rom0:MCMAN", 0, NULL
);
272 SifLoadModule("rom0:MCSERV", 0, NULL
);
274 if (modload_mask
& SYS_LOAD_PAD_MODULES
) {
275 SifLoadModule("rom0:PADMAN", 0, NULL
);
278 // clears modules list
279 memset((void *)&g_sysLoadedModBuffer
[0], 0, MAX_MODULES
*4);
282 sysLoadModuleBuffer(&discid_irx
, size_discid_irx
, 0, NULL
);
283 sysLoadModuleBuffer(&iomanx_irx
, size_iomanx_irx
, 0, NULL
);
284 sysLoadModuleBuffer(&filexio_irx
, size_filexio_irx
, 0, NULL
);
285 sysLoadModuleBuffer(&poweroff_irx
, size_poweroff_irx
, 0, NULL
);
287 sysLoadModuleBuffer(&genvmc_irx
, size_genvmc_irx
, 0, NULL
);
293 void sysPowerOff(void) {
299 // Get dev9 hardware type
300 dev9_hw_type
= *DEV9_R_146E
& 0xf0;
303 if ( dev9_hw_type
== 0x20 )
308 // Shutdown Expansion Bay
309 else if ( dev9_hw_type
== 0x30 )
313 *DEV9_R_1460
= *DEV9_R_1464
;
314 *DEV9_R_146C
= *DEV9_R_146C
& ~4;
315 *DEV9_R_1460
= *DEV9_R_146C
& ~1;
329 void delay(int count
) {
332 for (i
= 0; i
< count
; i
++) {
334 while(ret
--) asm("nop\nnop\nnop\nnop");
338 int sysPS3Detect(void) { //return 0=PS2 1=PS3-HARD 2=PS3-SOFT
340 void* buffer
= readFile("rom0:XPARAM2", -1, &size
);
342 for (i
= 0; i
< size
; i
++)
343 if (!strcmp((const char*) ((u32
) buffer
+ i
), "SCPS_110.01")) {
354 int sysSetIPConfig(char* ipconfig
) {
358 memset(ipconfig
, 0, IPCONFIG_MAX_LEN
);
361 // add ip to g_ipconfig buf
362 sprintf(str
, "%d.%d.%d.%d", ps2_ip
[0], ps2_ip
[1], ps2_ip
[2], ps2_ip
[3]);
363 strncpy(&ipconfig
[ipconfiglen
], str
, 15);
364 ipconfiglen
+= strlen(str
) + 1;
366 // add netmask to g_ipconfig buf
367 sprintf(str
, "%d.%d.%d.%d", ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3]);
368 strncpy(&ipconfig
[ipconfiglen
], str
, 15);
369 ipconfiglen
+= strlen(str
) + 1;
371 // add gateway to g_ipconfig buf
372 sprintf(str
, "%d.%d.%d.%d", ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
373 strncpy(&ipconfig
[ipconfiglen
], str
, 15);
374 ipconfiglen
+= strlen(str
) + 1;
379 static unsigned int crctab
[0x400];
381 unsigned int USBA_crc32(char *string
) {
382 int crc
, table
, count
, byte
;
384 for (table
=0; table
<256; table
++) {
387 for (count
=8; count
>0; count
--) {
388 if (crc
< 0) crc
= crc
<< 1;
389 else crc
= (crc
<< 1) ^ 0x04C11DB7;
391 crctab
[255-table
] = crc
;
395 byte
= string
[count
++];
396 crc
= crctab
[byte
^ ((crc
>> 24) & 0xFF)] ^ ((crc
<< 8) & 0xFFFFFF00);
397 } while (string
[count
-1] != 0);
402 int sysGetDiscID(char *hexDiscID
) {
404 cdInit(CDVD_INIT_NOCHECK
);
405 LOG("cdvd RPC inited\n");
406 if (cdStatus() == CDVD_STAT_OPEN
) // If tray is open, error
409 while (cdGetDiscType() == CDVD_TYPE_DETECT
) {;} // Trick : if tray is open before startup it detects it as closed...
410 if (cdGetDiscType() == CDVD_TYPE_NODISK
)
414 LOG("Disc drive is ready\n");
415 CdvdDiscType_t cdmode
= cdGetDiscType(); // If tray is closed, get disk type
416 if (cdmode
== CDVD_TYPE_NODISK
)
419 if ((cdmode
!= CDVD_TYPE_PS2DVD
) && (cdmode
!= CDVD_TYPE_PS2CD
) && (cdmode
!= CDVD_TYPE_PS2CDDA
)) {
422 LOG("Disc stopped\n");
423 LOG("Disc is not ps2 disc!\n");
429 LOG("Disc standby\n");
431 int fd
= fioOpen("discID:", O_RDONLY
);
435 LOG("Disc stopped\n");
439 unsigned char discID
[5];
440 memset(discID
, 0, 5);
441 fioRead(fd
, discID
, 5);
446 LOG("Disc stopped\n");
448 // convert to hexadecimal string
449 snprintf(hexDiscID
, 15, "%02X %02X %02X %02X %02X", discID
[0], discID
[1], discID
[2], discID
[3], discID
[4]);
450 LOG("PS2 Disc ID = %s\n", hexDiscID
);
455 int sysPcmciaCheck(void) {
459 ret
= fileXioDevctl("dev9x0:", 0x4401, NULL
, 0, NULL
, 0);
461 if (ret
== 0) // PCMCIA
467 void sysGetCDVDFSV(void **data_irx
, int *size_irx
)
469 *data_irx
= (void *)&cdvdfsv_irx
;
470 *size_irx
= size_cdvdfsv_irx
;
474 __asm__
__volatile__(
481 static void restoreSyscallHandler(void)
483 __asm__
__volatile__ (
484 "addiu $a0, $zero, 8\n\t"
485 "lui $a1, 0x8000\n\t"
486 "ori $a1, $a1, 0x0280\n\t"
487 "addiu $v1, $zero, 0x0e\n\t"
500 static void sendIrxKernelRAM(int size_cdvdman_irx
, void **cdvdman_irx
, int size_mcemu_irx
, void **mcemu_irx
) { // Send IOP modules that core must use to Kernel RAM
502 static void sendIrxKernelRAM(int size_cdvdman_irx
, void **cdvdman_irx
) { // Send IOP modules that core must use to Kernel RAM
505 restoreSyscallHandler();
507 void *irxtab
= (void *)0x80030010;
508 void *irxptr
= (void *)0x80030100;
509 irxptr_t irxptr_tab
[IRX_NUM
];
510 void *irxsrc
[IRX_NUM
];
512 u32 irxsize
, curIrxSize
;
515 irxptr_tab
[n
++].irxsize
= size_imgdrv_irx
;
516 irxptr_tab
[n
++].irxsize
= size_eesync_irx
;
517 irxptr_tab
[n
++].irxsize
= size_cdvdman_irx
;
518 irxptr_tab
[n
++].irxsize
= size_cdvdfsv_irx
;
519 irxptr_tab
[n
++].irxsize
= size_cddev_irx
;
520 irxptr_tab
[n
++].irxsize
= size_usbd_irx
;
521 irxptr_tab
[n
++].irxsize
= size_smsmap_irx
;
522 irxptr_tab
[n
++].irxsize
= size_udptty_irx
;
523 irxptr_tab
[n
++].irxsize
= size_ioptrap_irx
;
524 irxptr_tab
[n
++].irxsize
= size_ingame_smstcpip_irx
;
526 irxptr_tab
[n
++].irxsize
= size_mcemu_irx
;
530 irxsrc
[n
++] = (void *)&imgdrv_irx
;
531 irxsrc
[n
++] = (void *)&eesync_irx
;
532 irxsrc
[n
++] = (void *)cdvdman_irx
;
533 irxsrc
[n
++] = (void *)&cdvdfsv_irx
;
534 irxsrc
[n
++] = (void *)&cddev_irx
;
535 irxsrc
[n
++] = (void *)usbd_irx
;
536 irxsrc
[n
++] = (void *)&smsmap_irx
;
537 irxsrc
[n
++] = (void *)&udptty_irx
;
538 irxsrc
[n
++] = (void *)&ioptrap_irx
;
539 irxsrc
[n
++] = (void *)&ingame_smstcpip_irx
;
541 irxsrc
[n
++] = (void *)mcemu_irx
;
549 *(u32
*)0x80030000 = 0x80030010;
551 for (i
= 0; i
< IRX_NUM
; i
++) {
552 curIrxSize
= irxptr_tab
[i
].irxsize
;
553 if ((((u32
)irxptr
+ curIrxSize
) >= 0x80050000) && ((u32
)irxptr
< 0x80060000))
554 irxptr
= (void *)0x80060000;
555 irxptr_tab
[i
].irxaddr
= irxptr
;
557 if (curIrxSize
> 0) {
560 LOG("irx addr start: %08x end: %08x\n", (int)irxptr_tab
[i
].irxaddr
, (int)(irxptr_tab
[i
].irxaddr
+curIrxSize
));
564 memcpy((void *)irxptr_tab
[i
].irxaddr
, (void *)irxsrc
[i
], curIrxSize
);
566 irxptr
+= curIrxSize
;
567 irxsize
+= curIrxSize
;
571 memcpy((void *)irxtab
, (void *)&irxptr_tab
[0], sizeof(irxptr_tab
));
578 void sysLaunchLoaderElf(char *filename
, char *mode_str
, int size_cdvdman_irx
, void **cdvdman_irx
, int size_mcemu_irx
, void **mcemu_irx
, int compatflags
, int alt_ee_core
) {
580 void sysLaunchLoaderElf(char *filename
, char *mode_str
, int size_cdvdman_irx
, void **cdvdman_irx
, int compatflags
, int alt_ee_core
) {
588 char config_str
[255];
589 char ipconfig
[IPCONFIG_MAX_LEN
] __attribute__((aligned(64)));
591 sysSetIPConfig(ipconfig
); // TODO only needed for ETH mode, and already done in ethsupport.ethLoadModules
593 if (gExitPath
[0] == '\0')
594 strncpy(gExitPath
, "Browser", 32);
597 sendIrxKernelRAM(size_cdvdman_irx
, cdvdman_irx
, size_mcemu_irx
, mcemu_irx
);
599 sendIrxKernelRAM(size_cdvdman_irx
, cdvdman_irx
);
602 // NB: LOADER.ELF is embedded
604 boot_elf
= (u8
*)&alt_eecore_elf
;
606 boot_elf
= (u8
*)&eecore_elf
;
607 eh
= (elf_header_t
*)boot_elf
;
608 if (_lw((u32
)&eh
->ident
) != ELF_MAGIC
)
611 eph
= (elf_pheader_t
*)(boot_elf
+ eh
->phoff
);
613 // Scan through the ELF's program headers and copy them into RAM, then
614 // zero out any non-loaded regions.
615 for (i
= 0; i
< eh
->phnum
; i
++) {
616 if (eph
[i
].type
!= ELF_PT_LOAD
)
619 pdata
= (void *)(boot_elf
+ eph
[i
].offset
);
620 memcpy(eph
[i
].vaddr
, pdata
, eph
[i
].filesz
);
622 if (eph
[i
].memsz
> eph
[i
].filesz
)
623 memset(eph
[i
].vaddr
+ eph
[i
].filesz
, 0, eph
[i
].memsz
- eph
[i
].filesz
);
633 sprintf(config_str
, "%s %d %s %d %d %d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d", mode_str
, gDisableDebug
, gExitPath
, gUSBDelay
, gHDDSpindown
, \
634 ps2_ip
[0], ps2_ip
[1], ps2_ip
[2], ps2_ip
[3], \
635 ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3], \
636 ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
639 snprintf(cmask
, 10, "%d", compatflags
);
640 argv
[0] = config_str
;
644 ExecPS2((void *)eh
->entry
, 0, 3, argv
);
647 int sysExecElf(char *path
, int argc
, char **argv
) {
656 // NB: ELFLDR.ELF is embedded
657 boot_elf
= (u8
*)&elfldr_elf
;
658 eh
= (elf_header_t
*)boot_elf
;
659 if (_lw((u32
)&eh
->ident
) != ELF_MAGIC
)
662 eph
= (elf_pheader_t
*)(boot_elf
+ eh
->phoff
);
664 // Scan through the ELF's program headers and copy them into RAM, then
665 // zero out any non-loaded regions.
666 for (i
= 0; i
< eh
->phnum
; i
++) {
667 if (eph
[i
].type
!= ELF_PT_LOAD
)
670 pdata
= (void *)(boot_elf
+ eph
[i
].offset
);
671 memcpy(eph
[i
].vaddr
, pdata
, eph
[i
].filesz
);
673 if (eph
[i
].memsz
> eph
[i
].filesz
)
674 memset(eph
[i
].vaddr
+ eph
[i
].filesz
, 0, eph
[i
].memsz
- eph
[i
].filesz
);
685 for (i
=0; i
<argc
; i
++)
686 elf_argv
[i
+1] = argv
[i
];
688 ExecPS2((void *)eh
->entry
, 0, argc
+1, elf_argv
);
693 void sysApplyKernelPatches(void) {
697 int fd
= fioOpen("rom0:ROMVER", O_RDONLY
);
699 fioRead(fd
, romver
, sizeof(romver
));
702 // Check in rom0 for PS2 with Protokernel
706 if ((romver
[0] == '0')
707 && (romver
[1] == '1')
708 && (romver
[2] == '0')
709 && (romver
[9] == '0')) {
711 // if protokernel is unpatched
712 if (_lw((u32
)KSEG0(0x00002f88)) == 0x0c0015fa) {
714 // we copy the patching to its placement in kernel memory
715 u8
*elfptr
= (u8
*)&kpatch_10K_elf
;
716 elf_header_t
*eh
= (elf_header_t
*)elfptr
;
717 elf_pheader_t
*eph
= (elf_pheader_t
*)&elfptr
[eh
->phoff
];
720 for (i
= 0; i
< eh
->phnum
; i
++) {
721 if (eph
[i
].type
!= ELF_PT_LOAD
)
724 memcpy(eph
[i
].vaddr
, (void *)&elfptr
[eph
[i
].offset
], eph
[i
].filesz
);
726 if (eph
[i
].memsz
> eph
[i
].filesz
)
727 memset((void *)(eph
[i
].vaddr
+ eph
[i
].filesz
), 0, eph
[i
].memsz
- eph
[i
].filesz
);
730 // insert a JAL to our kernel code into the ExecPS2 syscall
731 _sw(JAL(eh
->entry
), KSEG0(0x00002f88));
743 int sysCheckMC(void) {
746 mcGetInfo(0, 0, &dummy
, &dummy
, &dummy
);
747 mcSync(0, NULL
, &ret
);
749 if( -1 == ret
|| 0 == ret
) return 0;
751 mcGetInfo(1, 0, &dummy
, &dummy
, &dummy
);
752 mcSync(0, NULL
, &ret
);
754 if( -1 == ret
|| 0 == ret
) return 1;
760 int sysCheckVMC(const char* prefix
, const char* sep
, char* name
, int createSize
) {
763 snprintf(path
, 255, "%sVMC%s%s.bin", prefix
, sep
, name
);
765 if (createSize
== -1)
768 int fd
= fileXioOpen(path
, O_RDONLY
, 0666);
770 size
= fileXioLseek(fd
, 0, SEEK_END
);
771 if (size
% 1048576) // invalid size, should be a an integer (8, 16, 32, 64, ...)
777 if (createSize
&& (createSize
!= size
))
781 if (createSize
&& (createSize
!= size
)) {
782 createVMCparam_t createParam
;
783 strcpy(createParam
.VMC_filename
, path
);
784 createParam
.VMC_size_mb
= createSize
;
785 createParam
.VMC_blocksize
= 16;
786 createParam
.VMC_thread_priority
= 0x0f;
787 createParam
.VMC_card_slot
= -1;
788 fileXioDevctl("genvmc:", 0xC0DE0001, (void*) &createParam
, sizeof(createParam
), NULL
, 0);