extracted code branching from ItemsList drawing and main drawing method
[open-ps2-loader.git] / src / system.c
blobab8ac8c02397090717a4b966aa15480f5202f041
1 /*
2 Copyright 2009, Ifcaro
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
5 */
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"
12 #ifdef VMC
13 typedef struct {
14 char VMC_filename[1024];
15 int VMC_size_mb;
16 int VMC_blocksize;
17 int VMC_thread_priority;
18 int VMC_card_slot;
19 } createVMCparam_t;
21 extern void *genvmc_irx;
22 extern int size_genvmc_irx;
23 #endif
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
103 // CDVD Registers
104 #define CDVD_R_SCMD ((volatile u8*)0xBF402016)
105 #define CDVD_R_SDIN ((volatile u8*)0xBF402017)
107 // DEV9 Registers
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))
120 typedef struct {
121 u8 ident[16]; // struct definition for ELF object header
122 u16 type;
123 u16 machine;
124 u32 version;
125 u32 entry;
126 u32 phoff;
127 u32 shoff;
128 u32 flags;
129 u16 ehsize;
130 u16 phentsize;
131 u16 phnum;
132 u16 shentsize;
133 u16 shnum;
134 u16 shstrndx;
135 } elf_header_t;
137 typedef struct {
138 u32 type; // struct definition for ELF program section header
139 u32 offset;
140 void *vaddr;
141 u32 paddr;
142 u32 filesz;
143 u32 memsz;
144 u32 flags;
145 u32 align;
146 } elf_pheader_t;
148 typedef struct {
149 void *irxaddr;
150 int irxsize;
151 } irxptr_t;
153 typedef struct {
154 char fileName[10];
155 u16 extinfoSize;
156 int fileSize;
157 } romdir_t;
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) {
166 index = i;
167 break;
170 if (i == MAX_MODULES)
171 return -1;
173 // check if the module was already loaded
174 for (i=0; i<MAX_MODULES; i++) {
175 if (g_sysLoadedModBuffer[i] == buffer) {
176 return 0;
180 // load the module
181 id = SifExecModuleBuffer(buffer, size, argc, argv, &ret);
182 if ((id < 0) || (ret))
183 return -2;
185 // add the module to the list
186 g_sysLoadedModBuffer[index] = buffer;
188 return 0;
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
206 // 0x00000000 // nop
207 // 0x0800033a(+text_start) // j rpc_handler_exit
208 // 0x00000000 // nop
210 smod_mod_info_t mod_info;
211 u8 jal_fioremove[4];
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))
221 return;
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));
236 FlushCache(0);
237 FlushCache(2);
240 void sysReset(int modload_mask) {
242 SifInitRpc(0);
243 cdInit(CDVD_INIT_NOCHECK);
244 cdInit(CDVD_INIT_EXIT);
246 while(!SifIopReset("rom0:UDNL rom0:EELOADCNF",0));
247 while(!SifIopSync());
249 fioExit();
250 SifExitIopHeap();
251 SifLoadFileExit();
252 SifExitRpc();
253 SifExitCmd();
255 SifInitRpc(0);
256 FlushCache(0);
257 FlushCache(2);
259 // init loadfile & iopheap services
260 SifLoadFileInit();
261 SifInitIopHeap();
263 // apply sbv patches
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);
281 // load modules
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);
286 #ifdef VMC
287 sysLoadModuleBuffer(&genvmc_irx, size_genvmc_irx, 0, NULL);
288 #endif
290 poweroffInit();
293 void sysPowerOff(void) {
294 u16 dev9_hw_type;
296 DIntr();
297 ee_kmode_enter();
299 // Get dev9 hardware type
300 dev9_hw_type = *DEV9_R_146E & 0xf0;
302 // Shutdown Pcmcia
303 if ( dev9_hw_type == 0x20 )
305 *DEV9_R_146C = 0;
306 *DEV9_R_1474 = 0;
308 // Shutdown Expansion Bay
309 else if ( dev9_hw_type == 0x30 )
311 *DEV9_R_1466 = 1;
312 *DEV9_R_1464 = 0;
313 *DEV9_R_1460 = *DEV9_R_1464;
314 *DEV9_R_146C = *DEV9_R_146C & ~4;
315 *DEV9_R_1460 = *DEV9_R_146C & ~1;
318 //Wait a sec
319 delay(5);
321 // PowerOff PS2
322 *CDVD_R_SDIN = 0;
323 *CDVD_R_SCMD = 0xF;
325 ee_kmode_exit();
326 EIntr();
329 void delay(int count) {
330 int i;
331 int ret;
332 for (i = 0; i < count; i++) {
333 ret = 0x01000000;
334 while(ret--) asm("nop\nnop\nnop\nnop");
338 int sysPS3Detect(void) { //return 0=PS2 1=PS3-HARD 2=PS3-SOFT
339 int i, size = -1;
340 void* buffer = readFile("rom0:XPARAM2", -1, &size);
341 if (buffer) {
342 for (i = 0; i < size; i++)
343 if (!strcmp((const char*) ((u32) buffer + i), "SCPS_110.01")) {
344 free(buffer);
345 return 2;
348 free(buffer);
349 return 1;
351 return 0;
354 int sysSetIPConfig(char* ipconfig) {
355 int ipconfiglen;
356 char str[16];
358 memset(ipconfig, 0, IPCONFIG_MAX_LEN);
359 ipconfiglen = 0;
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;
376 return ipconfiglen;
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++) {
385 crc = table << 24;
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;
394 do {
395 byte = string[count++];
396 crc = crctab[byte ^ ((crc >> 24) & 0xFF)] ^ ((crc << 8) & 0xFFFFFF00);
397 } while (string[count-1] != 0);
399 return crc;
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
407 return -1;
409 while (cdGetDiscType() == CDVD_TYPE_DETECT) {;} // Trick : if tray is open before startup it detects it as closed...
410 if (cdGetDiscType() == CDVD_TYPE_NODISK)
411 return -1;
413 cdDiskReady(0);
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)
417 return -1;
419 if ((cdmode != CDVD_TYPE_PS2DVD) && (cdmode != CDVD_TYPE_PS2CD) && (cdmode != CDVD_TYPE_PS2CDDA)) {
420 cdStop();
421 cdSync(0);
422 LOG("Disc stopped\n");
423 LOG("Disc is not ps2 disc!\n");
424 return -2;
427 cdStandby();
428 cdSync(0);
429 LOG("Disc standby\n");
431 int fd = fioOpen("discID:", O_RDONLY);
432 if (fd < 0) {
433 cdStop();
434 cdSync(0);
435 LOG("Disc stopped\n");
436 return -3;
439 unsigned char discID[5];
440 memset(discID, 0, 5);
441 fioRead(fd, discID, 5);
442 fioClose(fd);
444 cdStop();
445 cdSync(0);
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);
452 return 1;
455 int sysPcmciaCheck(void) {
456 int ret;
458 fileXioInit();
459 ret = fileXioDevctl("dev9x0:", 0x4401, NULL, 0, NULL, 0);
461 if (ret == 0) // PCMCIA
462 return 1;
464 return 0; // ExpBay
467 void sysGetCDVDFSV(void **data_irx, int *size_irx)
469 *data_irx = (void *)&cdvdfsv_irx;
470 *size_irx = size_cdvdfsv_irx;
473 void sysExecExit() {
474 __asm__ __volatile__(
475 " li $3, 0x04;"
476 " syscall;"
477 " nop;"
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"
488 "syscall\n\t"
489 "nop\n\t"
493 #ifdef VMC
494 #define IRX_NUM 11
495 #else
496 #define IRX_NUM 10
497 #endif
499 #ifdef VMC
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
501 #else
502 static void sendIrxKernelRAM(int size_cdvdman_irx, void **cdvdman_irx) { // Send IOP modules that core must use to Kernel RAM
503 #endif
505 restoreSyscallHandler();
507 void *irxtab = (void *)0x80030010;
508 void *irxptr = (void *)0x80030100;
509 irxptr_t irxptr_tab[IRX_NUM];
510 void *irxsrc[IRX_NUM];
511 int i, n;
512 u32 irxsize, curIrxSize;
514 n = 0;
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;
525 #ifdef VMC
526 irxptr_tab[n++].irxsize = size_mcemu_irx;
527 #endif
529 n = 0;
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;
540 #ifdef VMC
541 irxsrc[n++] = (void *)mcemu_irx;
542 #endif
544 irxsize = 0;
546 DIntr();
547 ee_kmode_enter();
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) {
558 ee_kmode_exit();
559 EIntr();
560 LOG("irx addr start: %08x end: %08x\n", (int)irxptr_tab[i].irxaddr, (int)(irxptr_tab[i].irxaddr+curIrxSize));
561 DIntr();
562 ee_kmode_enter();
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));
573 ee_kmode_exit();
574 EIntr();
577 #ifdef VMC
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) {
579 #else
580 void sysLaunchLoaderElf(char *filename, char *mode_str, int size_cdvdman_irx, void **cdvdman_irx, int compatflags, int alt_ee_core) {
581 #endif
582 u8 *boot_elf = NULL;
583 elf_header_t *eh;
584 elf_pheader_t *eph;
585 void *pdata;
586 int i;
587 char *argv[3];
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);
596 #ifdef VMC
597 sendIrxKernelRAM(size_cdvdman_irx, cdvdman_irx, size_mcemu_irx, mcemu_irx);
598 #else
599 sendIrxKernelRAM(size_cdvdman_irx, cdvdman_irx);
600 #endif
602 // NB: LOADER.ELF is embedded
603 if (alt_ee_core)
604 boot_elf = (u8 *)&alt_eecore_elf;
605 else
606 boot_elf = (u8 *)&eecore_elf;
607 eh = (elf_header_t *)boot_elf;
608 if (_lw((u32)&eh->ident) != ELF_MAGIC)
609 while (1);
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)
617 continue;
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);
626 // Let's go.
627 fioExit();
628 SifInitRpc(0);
629 SifExitRpc();
630 FlushCache(0);
631 FlushCache(2);
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]);
638 char cmask[10];
639 snprintf(cmask, 10, "%d", compatflags);
640 argv[0] = config_str;
641 argv[1] = filename;
642 argv[2] = cmask;
644 ExecPS2((void *)eh->entry, 0, 3, argv);
647 int sysExecElf(char *path, int argc, char **argv) {
648 u8 *boot_elf = NULL;
649 elf_header_t *eh;
650 elf_pheader_t *eph;
652 void *pdata;
653 int i;
654 char *elf_argv[1];
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)
660 while (1);
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)
668 continue;
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);
677 // Let's go.
678 fioExit();
679 SifInitRpc(0);
680 SifExitRpc();
681 FlushCache(0);
682 FlushCache(2);
684 elf_argv[0] = path;
685 for (i=0; i<argc; i++)
686 elf_argv[i+1] = argv[i];
688 ExecPS2((void *)eh->entry, 0, argc+1, elf_argv);
690 return 0;
693 void sysApplyKernelPatches(void) {
695 u8 romver[16];
697 int fd = fioOpen("rom0:ROMVER", O_RDONLY);
698 if (fd >= 0) {
699 fioRead(fd, romver, sizeof(romver));
700 fioClose(fd);
702 // Check in rom0 for PS2 with Protokernel
703 DIntr();
704 ee_kmode_enter();
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];
718 int i;
720 for (i = 0; i < eh->phnum; i++) {
721 if (eph[i].type != ELF_PT_LOAD)
722 continue;
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));
735 ee_kmode_exit();
736 EIntr();
738 FlushCache(0);
739 FlushCache(2);
743 int sysCheckMC(void) {
744 int dummy, ret;
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;
756 return -11;
759 #ifdef VMC
760 int sysCheckVMC(const char* prefix, const char* sep, char* name, int createSize) {
761 int size = -1;
762 char path[255];
763 snprintf(path, 255, "%sVMC%s%s.bin", prefix, sep, name);
765 if (createSize == -1)
766 fileXioRemove(path);
767 else {
768 int fd = fileXioOpen(path, O_RDONLY, 0666);
769 if (fd >= 0) {
770 size = fileXioLseek(fd, 0, SEEK_END);
771 if (size % 1048576) // invalid size, should be a an integer (8, 16, 32, 64, ...)
772 size = 0;
773 else
774 size /= 1048576;
776 fileXioClose(fd);
777 if (createSize && (createSize != size))
778 fileXioRemove(path);
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);
791 return size;
793 #endif