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
) {
354 cdInit(CDVD_INIT_NOCHECK
);
355 LOG("SYSTEM CDVD RPC inited\n");
356 if (cdStatus() == CDVD_STAT_OPEN
) // If tray is open, error
359 while (cdGetDiscType() == CDVD_TYPE_DETECT
) {;} // Trick : if tray is open before startup it detects it as closed...
360 if (cdGetDiscType() == CDVD_TYPE_NODISK
)
364 LOG("SYSTEM Disc drive is ready\n");
365 CdvdDiscType_t cdmode
= cdGetDiscType(); // If tray is closed, get disk type
366 if (cdmode
== CDVD_TYPE_NODISK
)
369 if ((cdmode
!= CDVD_TYPE_PS2DVD
) && (cdmode
!= CDVD_TYPE_PS2CD
) && (cdmode
!= CDVD_TYPE_PS2CDDA
)) {
372 LOG("SYSTEM Disc stopped, Disc is not ps2 disc!\n");
378 LOG("SYSTEM Disc standby\n");
380 int fd
= fioOpen("discID:", O_RDONLY
);
384 LOG("SYSTEM Disc stopped\n");
388 unsigned char discID
[5];
389 memset(discID
, 0, 5);
390 fioRead(fd
, discID
, 5);
395 LOG("SYSTEM Disc stopped\n");
397 // convert to hexadecimal string
398 snprintf(hexDiscID
, 15, "%02X %02X %02X %02X %02X", discID
[0], discID
[1], discID
[2], discID
[3], discID
[4]);
399 LOG("SYSTEM PS2 Disc ID = %s\n", hexDiscID
);
404 int sysPcmciaCheck(void) {
408 ret
= fileXioDevctl("dev9x0:", 0x4401, NULL
, 0, NULL
, 0);
410 if (ret
== 0) // PCMCIA
416 void sysGetCDVDFSV(void **data_irx
, int *size_irx
)
418 *data_irx
= (void *)&cdvdfsv_irx
;
419 *size_irx
= size_cdvdfsv_irx
;
423 __asm__
__volatile__(
430 static void restoreSyscallHandler(void)
432 __asm__
__volatile__ (
433 "addiu $a0, $zero, 8\n\t"
434 "lui $a1, 0x8000\n\t"
435 "ori $a1, $a1, 0x0280\n\t"
436 "addiu $v1, $zero, 0x0e\n\t"
449 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
451 static void sendIrxKernelRAM(int size_cdvdman_irx
, void **cdvdman_irx
) { // Send IOP modules that core must use to Kernel RAM
454 restoreSyscallHandler();
456 void *irxtab
= (void *)0x80033010;
457 void *irxptr
= (void *)0x80033100;
458 irxptr_t irxptr_tab
[IRX_NUM
];
459 void *irxsrc
[IRX_NUM
];
461 u32 irxsize
, curIrxSize
;
464 irxptr_tab
[n
++].irxsize
= size_imgdrv_irx
;
465 irxptr_tab
[n
++].irxsize
= size_eesync_irx
;
466 irxptr_tab
[n
++].irxsize
= size_cdvdman_irx
;
467 irxptr_tab
[n
++].irxsize
= size_cdvdfsv_irx
;
468 irxptr_tab
[n
++].irxsize
= size_cddev_irx
;
469 irxptr_tab
[n
++].irxsize
= size_usbd_irx
;
470 irxptr_tab
[n
++].irxsize
= size_smsmap_irx
;
471 irxptr_tab
[n
++].irxsize
= size_udptty_irx
;
472 irxptr_tab
[n
++].irxsize
= size_ioptrap_irx
;
473 irxptr_tab
[n
++].irxsize
= size_ingame_smstcpip_irx
;
475 irxptr_tab
[n
++].irxsize
= size_mcemu_irx
;
479 irxsrc
[n
++] = (void *)&imgdrv_irx
;
480 irxsrc
[n
++] = (void *)&eesync_irx
;
481 irxsrc
[n
++] = (void *)cdvdman_irx
;
482 irxsrc
[n
++] = (void *)&cdvdfsv_irx
;
483 irxsrc
[n
++] = (void *)&cddev_irx
;
484 irxsrc
[n
++] = (void *)usbd_irx
;
485 irxsrc
[n
++] = (void *)&smsmap_irx
;
486 irxsrc
[n
++] = (void *)&udptty_irx
;
487 irxsrc
[n
++] = (void *)&ioptrap_irx
;
488 irxsrc
[n
++] = (void *)&ingame_smstcpip_irx
;
490 irxsrc
[n
++] = (void *)mcemu_irx
;
498 *(u32
*)0x80033000 = 0x80033010;
500 for (i
= 0; i
< IRX_NUM
; i
++) {
501 curIrxSize
= irxptr_tab
[i
].irxsize
;
502 if ((((u32
)irxptr
+ curIrxSize
) >= 0x80050000) && ((u32
)irxptr
< 0x80060000))
503 irxptr
= (void *)0x80060000;
504 irxptr_tab
[i
].irxaddr
= irxptr
;
506 if (curIrxSize
> 0) {
509 LOG("SYSTEM IRX address start: %08x end: %08x\n", (int)irxptr_tab
[i
].irxaddr
, (int)(irxptr_tab
[i
].irxaddr
+curIrxSize
));
513 memcpy((void *)irxptr_tab
[i
].irxaddr
, (void *)irxsrc
[i
], curIrxSize
);
515 irxptr
+= curIrxSize
;
516 irxsize
+= curIrxSize
;
520 memcpy((void *)irxtab
, (void *)&irxptr_tab
[0], sizeof(irxptr_tab
));
527 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
) {
529 void sysLaunchLoaderElf(char *filename
, char *mode_str
, int size_cdvdman_irx
, void **cdvdman_irx
, int compatflags
, int alt_ee_core
) {
537 char config_str
[255];
538 char ipconfig
[IPCONFIG_MAX_LEN
] __attribute__((aligned(64)));
540 sysSetIPConfig(ipconfig
); // TODO only needed for ETH mode, and already done in ethsupport.ethLoadModules
542 if (gExitPath
[0] == '\0')
543 strncpy(gExitPath
, "Browser", 32);
546 LOG("SYSTEM LaunchLoaderElf called with size_mcemu_irx = %d\n", size_mcemu_irx
);
547 sendIrxKernelRAM(size_cdvdman_irx
, cdvdman_irx
, size_mcemu_irx
, mcemu_irx
);
549 sendIrxKernelRAM(size_cdvdman_irx
, cdvdman_irx
);
552 // NB: LOADER.ELF is embedded
554 boot_elf
= (u8
*)&alt_eecore_elf
;
556 boot_elf
= (u8
*)&eecore_elf
;
557 eh
= (elf_header_t
*)boot_elf
;
558 if (_lw((u32
)&eh
->ident
) != ELF_MAGIC
)
561 eph
= (elf_pheader_t
*)(boot_elf
+ eh
->phoff
);
563 // Scan through the ELF's program headers and copy them into RAM, then
564 // zero out any non-loaded regions.
565 for (i
= 0; i
< eh
->phnum
; i
++) {
566 if (eph
[i
].type
!= ELF_PT_LOAD
)
569 pdata
= (void *)(boot_elf
+ eph
[i
].offset
);
570 memcpy(eph
[i
].vaddr
, pdata
, eph
[i
].filesz
);
572 if (eph
[i
].memsz
> eph
[i
].filesz
)
573 memset(eph
[i
].vaddr
+ eph
[i
].filesz
, 0, eph
[i
].memsz
- eph
[i
].filesz
);
583 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
, \
584 ps2_ip
[0], ps2_ip
[1], ps2_ip
[2], ps2_ip
[3], \
585 ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3], \
586 ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
589 snprintf(cmask
, 10, "%d", compatflags
);
590 argv
[0] = config_str
;
594 ExecPS2((void *)eh
->entry
, 0, 3, argv
);
597 int sysExecElf(char *path
, int argc
, char **argv
) {
606 // NB: ELFLDR.ELF is embedded
607 boot_elf
= (u8
*)&elfldr_elf
;
608 eh
= (elf_header_t
*)boot_elf
;
609 if (_lw((u32
)&eh
->ident
) != ELF_MAGIC
)
612 eph
= (elf_pheader_t
*)(boot_elf
+ eh
->phoff
);
614 // Scan through the ELF's program headers and copy them into RAM, then
615 // zero out any non-loaded regions.
616 for (i
= 0; i
< eh
->phnum
; i
++) {
617 if (eph
[i
].type
!= ELF_PT_LOAD
)
620 pdata
= (void *)(boot_elf
+ eph
[i
].offset
);
621 memcpy(eph
[i
].vaddr
, pdata
, eph
[i
].filesz
);
623 if (eph
[i
].memsz
> eph
[i
].filesz
)
624 memset(eph
[i
].vaddr
+ eph
[i
].filesz
, 0, eph
[i
].memsz
- eph
[i
].filesz
);
635 for (i
=0; i
<argc
; i
++)
636 elf_argv
[i
+1] = argv
[i
];
638 ExecPS2((void *)eh
->entry
, 0, argc
+1, elf_argv
);
643 void sysApplyKernelPatches(void) {
647 int fd
= fioOpen("rom0:ROMVER", O_RDONLY
);
649 fioRead(fd
, romver
, sizeof(romver
));
652 // Check in rom0 for PS2 with Protokernel
653 if ((romver
[0] == '0')
654 && (romver
[1] == '1')
655 && (romver
[2] == '0')
656 && (romver
[9] == '0')) {
658 sbv_patch_protokernel();
663 int sysCheckMC(void) {
666 mcGetInfo(0, 0, &dummy
, &dummy
, &dummy
);
667 mcSync(0, NULL
, &ret
);
669 if( -1 == ret
|| 0 == ret
) return 0;
671 mcGetInfo(1, 0, &dummy
, &dummy
, &dummy
);
672 mcSync(0, NULL
, &ret
);
674 if( -1 == ret
|| 0 == ret
) return 1;
680 // createSize == -1 : delete, createSize == 0 : probing, createSize > 0 : creation
681 int sysCheckVMC(const char* prefix
, const char* sep
, char* name
, int createSize
, vmc_superblock_t
* vmc_superblock
) {
684 snprintf(path
, 255, "%sVMC%s%s.bin", prefix
, sep
, name
);
686 if (createSize
== -1)
689 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
);
691 size
= fileXioLseek(fd
, 0, SEEK_END
);
693 if (vmc_superblock
) {
694 memset(vmc_superblock
, 0, sizeof(vmc_superblock_t
));
695 fileXioLseek(fd
, 0, SEEK_SET
);
696 fileXioRead(fd
, (void*)vmc_superblock
, sizeof(vmc_superblock_t
));
698 LOG("SYSTEM File size : 0x%X\n", size
);
699 LOG("SYSTEM Magic : %s\n", vmc_superblock
->magic
);
700 LOG("SYSTEM Card type : %d\n", vmc_superblock
->mc_type
);
701 LOG("SYSTEM Flags : 0x%X\n", (vmc_superblock
->mc_flag
& 0xFF) | 0x100);
702 LOG("SYSTEM Page_size : 0x%X\n", vmc_superblock
->page_size
);
703 LOG("SYSTEM Block_size : 0x%X\n", vmc_superblock
->pages_per_block
);
704 LOG("SYSTEM Card_size : 0x%X\n", vmc_superblock
->pages_per_cluster
* vmc_superblock
->clusters_per_card
);
706 if(!strncmp(vmc_superblock
->magic
, "Sony PS2 Memory Card Format", 27) && vmc_superblock
->mc_type
== 0x2
707 && size
== vmc_superblock
->pages_per_cluster
* vmc_superblock
->clusters_per_card
* vmc_superblock
->page_size
) {
708 LOG("SYSTEM VMC file structure valid: %s\n", path
);
713 if (size
% 1048576) // invalid size, should be a an integer (8, 16, 32, 64, ...)
720 if (createSize
&& (createSize
!= size
))
724 if (createSize
&& (createSize
!= size
)) {
725 createVMCparam_t createParam
;
726 strcpy(createParam
.VMC_filename
, path
);
727 createParam
.VMC_size_mb
= createSize
;
728 createParam
.VMC_blocksize
= 16;
729 createParam
.VMC_thread_priority
= 0x0f;
730 createParam
.VMC_card_slot
= -1;
731 fileXioDevctl("genvmc:", 0xC0DE0001, (void*) &createParam
, sizeof(createParam
), NULL
, 0);