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 sysReset(int modload_mask
) {
194 cdInit(CDVD_INIT_NOCHECK
);
195 cdInit(CDVD_INIT_EXIT
);
197 while(!SifIopReset("rom0:UDNL rom0:EELOADCNF",0));
198 while(!SifIopSync());
210 // init loadfile & iopheap services
215 sbv_patch_enable_lmb();
216 sbv_patch_disable_prefix_check();
217 sbv_patch_fioremove();
219 SifLoadModule("rom0:SIO2MAN", 0, NULL
);
221 if (modload_mask
& SYS_LOAD_MC_MODULES
) {
222 SifLoadModule("rom0:MCMAN", 0, NULL
);
223 SifLoadModule("rom0:MCSERV", 0, NULL
);
225 if (modload_mask
& SYS_LOAD_PAD_MODULES
) {
226 SifLoadModule("rom0:PADMAN", 0, NULL
);
229 // clears modules list
230 memset((void *)&g_sysLoadedModBuffer
[0], 0, MAX_MODULES
*4);
233 sysLoadModuleBuffer(&discid_irx
, size_discid_irx
, 0, NULL
);
234 sysLoadModuleBuffer(&iomanx_irx
, size_iomanx_irx
, 0, NULL
);
235 sysLoadModuleBuffer(&filexio_irx
, size_filexio_irx
, 0, NULL
);
236 sysLoadModuleBuffer(&poweroff_irx
, size_poweroff_irx
, 0, NULL
);
238 sysLoadModuleBuffer(&genvmc_irx
, size_genvmc_irx
, 0, NULL
);
244 void sysPowerOff(void) {
250 // Get dev9 hardware type
251 dev9_hw_type
= *DEV9_R_146E
& 0xf0;
254 if ( dev9_hw_type
== 0x20 )
259 // Shutdown Expansion Bay
260 else if ( dev9_hw_type
== 0x30 )
264 *DEV9_R_1460
= *DEV9_R_1464
;
265 *DEV9_R_146C
= *DEV9_R_146C
& ~4;
266 *DEV9_R_1460
= *DEV9_R_146C
& ~1;
280 void delay(int count
) {
283 for (i
= 0; i
< count
; i
++) {
285 while(ret
--) asm("nop\nnop\nnop\nnop");
289 int sysPS3Detect(void) { //return 0=PS2 1=PS3-HARD 2=PS3-SOFT
291 void* buffer
= readFile("rom0:XPARAM2", -1, &size
);
293 for (i
= 0; i
< size
; i
++)
294 if (!strcmp((const char*) ((u32
) buffer
+ i
), "SCPS_110.01")) {
305 int sysSetIPConfig(char* ipconfig
) {
309 memset(ipconfig
, 0, IPCONFIG_MAX_LEN
);
312 // add ip to g_ipconfig buf
313 sprintf(str
, "%d.%d.%d.%d", ps2_ip
[0], ps2_ip
[1], ps2_ip
[2], ps2_ip
[3]);
314 strncpy(&ipconfig
[ipconfiglen
], str
, 15);
315 ipconfiglen
+= strlen(str
) + 1;
317 // add netmask to g_ipconfig buf
318 sprintf(str
, "%d.%d.%d.%d", ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3]);
319 strncpy(&ipconfig
[ipconfiglen
], str
, 15);
320 ipconfiglen
+= strlen(str
) + 1;
322 // add gateway to g_ipconfig buf
323 sprintf(str
, "%d.%d.%d.%d", ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
324 strncpy(&ipconfig
[ipconfiglen
], str
, 15);
325 ipconfiglen
+= strlen(str
) + 1;
330 static unsigned int crctab
[0x400];
332 unsigned int USBA_crc32(char *string
) {
333 int crc
, table
, count
, byte
;
335 for (table
=0; table
<256; table
++) {
338 for (count
=8; count
>0; count
--) {
339 if (crc
< 0) crc
= crc
<< 1;
340 else crc
= (crc
<< 1) ^ 0x04C11DB7;
342 crctab
[255-table
] = crc
;
346 byte
= string
[count
++];
347 crc
= crctab
[byte
^ ((crc
>> 24) & 0xFF)] ^ ((crc
<< 8) & 0xFFFFFF00);
348 } while (string
[count
-1] != 0);
353 int sysGetDiscID(char *hexDiscID
) {
355 cdInit(CDVD_INIT_NOCHECK
);
356 LOG("cdvd RPC inited\n");
357 if (cdStatus() == CDVD_STAT_OPEN
) // If tray is open, error
360 while (cdGetDiscType() == CDVD_TYPE_DETECT
) {;} // Trick : if tray is open before startup it detects it as closed...
361 if (cdGetDiscType() == CDVD_TYPE_NODISK
)
365 LOG("Disc drive is ready\n");
366 CdvdDiscType_t cdmode
= cdGetDiscType(); // If tray is closed, get disk type
367 if (cdmode
== CDVD_TYPE_NODISK
)
370 if ((cdmode
!= CDVD_TYPE_PS2DVD
) && (cdmode
!= CDVD_TYPE_PS2CD
) && (cdmode
!= CDVD_TYPE_PS2CDDA
)) {
373 LOG("Disc stopped\n");
374 LOG("Disc is not ps2 disc!\n");
380 LOG("Disc standby\n");
382 int fd
= fioOpen("discID:", O_RDONLY
);
386 LOG("Disc stopped\n");
390 unsigned char discID
[5];
391 memset(discID
, 0, 5);
392 fioRead(fd
, discID
, 5);
397 LOG("Disc stopped\n");
399 // convert to hexadecimal string
400 snprintf(hexDiscID
, 15, "%02X %02X %02X %02X %02X", discID
[0], discID
[1], discID
[2], discID
[3], discID
[4]);
401 LOG("PS2 Disc ID = %s\n", hexDiscID
);
406 int sysPcmciaCheck(void) {
410 ret
= fileXioDevctl("dev9x0:", 0x4401, NULL
, 0, NULL
, 0);
412 if (ret
== 0) // PCMCIA
418 void sysGetCDVDFSV(void **data_irx
, int *size_irx
)
420 *data_irx
= (void *)&cdvdfsv_irx
;
421 *size_irx
= size_cdvdfsv_irx
;
425 __asm__
__volatile__(
432 static void restoreSyscallHandler(void)
434 __asm__
__volatile__ (
435 "addiu $a0, $zero, 8\n\t"
436 "lui $a1, 0x8000\n\t"
437 "ori $a1, $a1, 0x0280\n\t"
438 "addiu $v1, $zero, 0x0e\n\t"
451 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
453 static void sendIrxKernelRAM(int size_cdvdman_irx
, void **cdvdman_irx
) { // Send IOP modules that core must use to Kernel RAM
456 restoreSyscallHandler();
458 void *irxtab
= (void *)0x80033010;
459 void *irxptr
= (void *)0x80033100;
460 irxptr_t irxptr_tab
[IRX_NUM
];
461 void *irxsrc
[IRX_NUM
];
463 u32 irxsize
, curIrxSize
;
466 irxptr_tab
[n
++].irxsize
= size_imgdrv_irx
;
467 irxptr_tab
[n
++].irxsize
= size_eesync_irx
;
468 irxptr_tab
[n
++].irxsize
= size_cdvdman_irx
;
469 irxptr_tab
[n
++].irxsize
= size_cdvdfsv_irx
;
470 irxptr_tab
[n
++].irxsize
= size_cddev_irx
;
471 irxptr_tab
[n
++].irxsize
= size_usbd_irx
;
472 irxptr_tab
[n
++].irxsize
= size_smsmap_irx
;
473 irxptr_tab
[n
++].irxsize
= size_udptty_irx
;
474 irxptr_tab
[n
++].irxsize
= size_ioptrap_irx
;
475 irxptr_tab
[n
++].irxsize
= size_ingame_smstcpip_irx
;
477 irxptr_tab
[n
++].irxsize
= size_mcemu_irx
;
481 irxsrc
[n
++] = (void *)&imgdrv_irx
;
482 irxsrc
[n
++] = (void *)&eesync_irx
;
483 irxsrc
[n
++] = (void *)cdvdman_irx
;
484 irxsrc
[n
++] = (void *)&cdvdfsv_irx
;
485 irxsrc
[n
++] = (void *)&cddev_irx
;
486 irxsrc
[n
++] = (void *)usbd_irx
;
487 irxsrc
[n
++] = (void *)&smsmap_irx
;
488 irxsrc
[n
++] = (void *)&udptty_irx
;
489 irxsrc
[n
++] = (void *)&ioptrap_irx
;
490 irxsrc
[n
++] = (void *)&ingame_smstcpip_irx
;
492 irxsrc
[n
++] = (void *)mcemu_irx
;
500 *(u32
*)0x80033000 = 0x80033010;
502 for (i
= 0; i
< IRX_NUM
; i
++) {
503 curIrxSize
= irxptr_tab
[i
].irxsize
;
504 if ((((u32
)irxptr
+ curIrxSize
) >= 0x80050000) && ((u32
)irxptr
< 0x80060000))
505 irxptr
= (void *)0x80060000;
506 irxptr_tab
[i
].irxaddr
= irxptr
;
508 if (curIrxSize
> 0) {
511 LOG("irx addr start: %08x end: %08x\n", (int)irxptr_tab
[i
].irxaddr
, (int)(irxptr_tab
[i
].irxaddr
+curIrxSize
));
515 memcpy((void *)irxptr_tab
[i
].irxaddr
, (void *)irxsrc
[i
], curIrxSize
);
517 irxptr
+= curIrxSize
;
518 irxsize
+= curIrxSize
;
522 memcpy((void *)irxtab
, (void *)&irxptr_tab
[0], sizeof(irxptr_tab
));
529 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
) {
531 void sysLaunchLoaderElf(char *filename
, char *mode_str
, int size_cdvdman_irx
, void **cdvdman_irx
, int compatflags
, int alt_ee_core
) {
539 char config_str
[255];
540 char ipconfig
[IPCONFIG_MAX_LEN
] __attribute__((aligned(64)));
542 sysSetIPConfig(ipconfig
); // TODO only needed for ETH mode, and already done in ethsupport.ethLoadModules
544 if (gExitPath
[0] == '\0')
545 strncpy(gExitPath
, "Browser", 32);
548 LOG("sysLaunchLoaderElf started with size_mcemu_irx = %d\n", size_mcemu_irx
);
549 sendIrxKernelRAM(size_cdvdman_irx
, cdvdman_irx
, size_mcemu_irx
, mcemu_irx
);
551 sendIrxKernelRAM(size_cdvdman_irx
, cdvdman_irx
);
554 // NB: LOADER.ELF is embedded
556 boot_elf
= (u8
*)&alt_eecore_elf
;
558 boot_elf
= (u8
*)&eecore_elf
;
559 eh
= (elf_header_t
*)boot_elf
;
560 if (_lw((u32
)&eh
->ident
) != ELF_MAGIC
)
563 eph
= (elf_pheader_t
*)(boot_elf
+ eh
->phoff
);
565 // Scan through the ELF's program headers and copy them into RAM, then
566 // zero out any non-loaded regions.
567 for (i
= 0; i
< eh
->phnum
; i
++) {
568 if (eph
[i
].type
!= ELF_PT_LOAD
)
571 pdata
= (void *)(boot_elf
+ eph
[i
].offset
);
572 memcpy(eph
[i
].vaddr
, pdata
, eph
[i
].filesz
);
574 if (eph
[i
].memsz
> eph
[i
].filesz
)
575 memset(eph
[i
].vaddr
+ eph
[i
].filesz
, 0, eph
[i
].memsz
- eph
[i
].filesz
);
585 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
, \
586 ps2_ip
[0], ps2_ip
[1], ps2_ip
[2], ps2_ip
[3], \
587 ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3], \
588 ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
591 snprintf(cmask
, 10, "%d", compatflags
);
592 argv
[0] = config_str
;
596 ExecPS2((void *)eh
->entry
, 0, 3, argv
);
599 int sysExecElf(char *path
, int argc
, char **argv
) {
608 // NB: ELFLDR.ELF is embedded
609 boot_elf
= (u8
*)&elfldr_elf
;
610 eh
= (elf_header_t
*)boot_elf
;
611 if (_lw((u32
)&eh
->ident
) != ELF_MAGIC
)
614 eph
= (elf_pheader_t
*)(boot_elf
+ eh
->phoff
);
616 // Scan through the ELF's program headers and copy them into RAM, then
617 // zero out any non-loaded regions.
618 for (i
= 0; i
< eh
->phnum
; i
++) {
619 if (eph
[i
].type
!= ELF_PT_LOAD
)
622 pdata
= (void *)(boot_elf
+ eph
[i
].offset
);
623 memcpy(eph
[i
].vaddr
, pdata
, eph
[i
].filesz
);
625 if (eph
[i
].memsz
> eph
[i
].filesz
)
626 memset(eph
[i
].vaddr
+ eph
[i
].filesz
, 0, eph
[i
].memsz
- eph
[i
].filesz
);
637 for (i
=0; i
<argc
; i
++)
638 elf_argv
[i
+1] = argv
[i
];
640 ExecPS2((void *)eh
->entry
, 0, argc
+1, elf_argv
);
645 void sysApplyKernelPatches(void) {
649 int fd
= fioOpen("rom0:ROMVER", O_RDONLY
);
651 fioRead(fd
, romver
, sizeof(romver
));
654 // Check in rom0 for PS2 with Protokernel
655 if ((romver
[0] == '0')
656 && (romver
[1] == '1')
657 && (romver
[2] == '0')
658 && (romver
[9] == '0')) {
660 sbv_patch_protokernel();
665 int sysCheckMC(void) {
668 mcGetInfo(0, 0, &dummy
, &dummy
, &dummy
);
669 mcSync(0, NULL
, &ret
);
671 if( -1 == ret
|| 0 == ret
) return 0;
673 mcGetInfo(1, 0, &dummy
, &dummy
, &dummy
);
674 mcSync(0, NULL
, &ret
);
676 if( -1 == ret
|| 0 == ret
) return 1;
682 // createSize == -1 : delete, createSize == 0 : probing, createSize > 0 : creation
683 int sysCheckVMC(const char* prefix
, const char* sep
, char* name
, int createSize
, vmc_superblock_t
* vmc_superblock
) {
686 snprintf(path
, 255, "%sVMC%s%s.bin", prefix
, sep
, name
);
688 if (createSize
== -1)
691 int fd
= fileXioOpen(path
, O_RDONLY
, FIO_S_IRUSR
| FIO_S_IWUSR
| FIO_S_IXUSR
| FIO_S_IRGRP
| FIO_S_IWGRP
| FIO_S_IXGRP
| FIO_S_IROTH
| FIO_S_IWOTH
| FIO_S_IXOTH
);
693 size
= fileXioLseek(fd
, 0, SEEK_END
);
695 if (vmc_superblock
) {
696 memset(vmc_superblock
, 0, sizeof(vmc_superblock_t
));
697 fileXioLseek(fd
, 0, SEEK_SET
);
698 fileXioRead(fd
, (void*)vmc_superblock
, sizeof(vmc_superblock_t
));
700 LOG("File size : 0x%X\n", size
);
701 LOG("Magic : %s\n", vmc_superblock
->magic
);
702 LOG("Card type : %d\n", vmc_superblock
->mc_type
);
703 LOG("Flags : 0x%X\n", (vmc_superblock
->mc_flag
& 0xFF) | 0x100);
704 LOG("Page_size : 0x%X\n", vmc_superblock
->page_size
);
705 LOG("Block_size : 0x%X\n", vmc_superblock
->pages_per_block
);
706 LOG("Card_size : 0x%X\n", vmc_superblock
->pages_per_cluster
* vmc_superblock
->clusters_per_card
);
708 if(!strncmp(vmc_superblock
->magic
, "Sony PS2 Memory Card Format", 27) && vmc_superblock
->mc_type
== 0x2
709 && size
== vmc_superblock
->pages_per_cluster
* vmc_superblock
->clusters_per_card
* vmc_superblock
->page_size
) {
710 LOG("VMC file structure valid: %s\n", path
);
715 if (size
% 1048576) // invalid size, should be a an integer (8, 16, 32, 64, ...)
722 if (createSize
&& (createSize
!= size
))
726 if (createSize
&& (createSize
!= size
)) {
727 createVMCparam_t createParam
;
728 strcpy(createParam
.VMC_filename
, path
);
729 createParam
.VMC_size_mb
= createSize
;
730 createParam
.VMC_blocksize
= 16;
731 createParam
.VMC_thread_priority
= 0x0f;
732 createParam
.VMC_card_slot
= -1;
733 fileXioDevctl("genvmc:", 0xC0DE0001, (void*) &createParam
, sizeof(createParam
), NULL
, 0);