int readPrx( const char * file, int heap_id, u8 ** outbuf ) { log( "read %s to memory!\n", file ); int fd = sceIoOpen( file, PSP_O_RDONLY, 0644 ); if ( fd < 0 ) { log( "failed in opening %s\n", file ); return -1; } u8 * inbuf = ( u8 * )sceKernelAllocHeapMemory( heap_id, CXMB_MKCTF_BUF_SIZE / 2 ); int size = sceIoRead( fd, inbuf, CXMB_MKCTF_BUF_SIZE / 2 ); if ( inbuf[0x150] == 0x1F && inbuf[0x151] == 0x8B ) { log( "uncompress gzip file!\n" ); *outbuf = ( u8 * )sceKernelAllocHeapMemory( heap_id, CXMB_MKCTF_BUF_SIZE / 2 ); int size = sceKernelGzipDecompress( *outbuf, CXMB_MKCTF_BUF_SIZE / 2, &inbuf[0x150], 0 ); log( "uncompressed size %08x!\n", size ); sceKernelFreeHeapMemory( heap_id, inbuf ); if ( size > 0 && size < CXMB_MAX_FILE_SIZE ) { return size; } else { sceKernelFreeHeapMemory( heap_id, outbuf ); return -1; } } else { *outbuf = inbuf; return size; } return -1; }
/* * Initialize the System Call table. It is initialized the very * first time a SCE_LIB_SYSCALL_EXPORT resident library is * registered to the system. The table makes room for * SYSCALL_TABLE_FUNCTION_TABLE_ENTRIES functions to be stored * in it. These function pointer slots are initialized to the * address of the function "UndefSyscall", which simply returns an * error, marking a slot as currently being unused. * * In addition, the internal SyscallEntryTable linked list is initialized * and g_pSysEntControl is set to the top member of it. * * @param seed Used to set the start address of the system call table. * @param lcSyscallTable Receive a pointer to the allocated system * call table. * * @return 0 on success. */ s32 SyscallTableInit(u32 seed, SceSyscallTable **syscallTable) { u32 i; s32 status; SceSyscallTable *sysCallTable; sysCallTable = sceKernelAllocHeapMemory(g_loadCoreHeap(), SYSCALL_TABLE_SIZE); if (sysCallTable == NULL) return SCE_ERROR_KERNEL_ERROR; sysCallTable->next = NULL; sysCallTable->seed = seed << 2; sysCallTable->funcTableSize = SYSCALL_TABLE_FUNCTION_TABLE_SIZE; sysCallTable->tableSize = SYSCALL_TABLE_SIZE; //0x000003B0 - 0x000003C8 for (i = 0; i < SYSCALL_TABLE_FUNCTION_TABLE_ENTRIES; i++) sysCallTable->syscalls[i] = (void (*)())UndefSyscall; //0x000003D0 - 0x000003F8 initialSysEntTable[0].next = NULL; for (i = 0; i < TOP_SYSCALL_ENTRY_TABLE; i++) initialSysEntTable[i + 1].next = &initialSysEntTable[i]; g_pFreeSysEnt = &initialSysEntTable[TOP_SYSCALL_ENTRY_TABLE]; //0x0000040C if (g_pFreeSysEnt == NULL) { //0x00000410 g_pSysEntControl = (SceSysCallEntryTable *)sceKernelAllocHeapMemory(g_loadCoreHeap(), sizeof(SceSysCallEntryTable)); //0x00000498 & 0x000004A4 } else { g_pSysEntControl = g_pFreeSysEnt; //0x00000420 g_pFreeSysEnt = g_pFreeSysEnt->next; //0x0000041C } //0x00000424 - 0x00000440 /* Initialize the first SYSCALL table entry. */ g_pSysEntControl->next = NULL; g_pSysEntControl->inUse = SCE_FALSE; g_pSysEntControl->numEntries = SYSCALL_TABLE_DEFAULT_ENTRIES; g_pSysEntControl->startAddr = 0; status = sceKernelRegisterSystemCallTable(sysCallTable); //0x0000043C if (status != SCE_ERROR_OK) { //0x00000444 sceKernelFreeHeapMemory(g_loadCoreHeap(), sysCallTable); //0x00000478 & 0x00000484 return status; } *syscallTable = sysCallTable; return SCE_ERROR_OK; }
int IoOpen_new( PspIoDrvFileArg * arg, char * file, int flags, SceMode mode ) { PspIoDrvArg * drv = arg->drv; if( ctf_handler && arg->fs_num == 0 ) { ctf_handler[handler_count].num = inCtf( file ); if ( ctf_handler[handler_count].num >= 0 ) { log( "replace %s\n", file ); arg->drv = ms_drv; int ret = fatms_drv->funcs->IoOpen( arg, theme_file, flags, mode); if ( ret < 0 ) { arg->drv = drv; } else { ctf_handler[handler_count].offset = fatms_drv->funcs->IoLseek( arg, ctf_header[ctf_handler[handler_count].num].start, PSP_SEEK_SET ); ctf_handler[handler_count].arg = arg->arg; handler_count ++; if ( handler_count % 32 == 0 ) { CtfHandler * tmp = sceKernelAllocHeapMemory( mem_id, sizeof( CtfHandler ) * ( handler_count + 32 ) ); memcpy( tmp, ctf_handler, sizeof( CtfHandler ) * handler_count ); sceKernelFreeHeapMemory( mem_id, ctf_handler ); ctf_handler = tmp; } arg->drv = drv; return ret; } } } int ret = IoOpen( arg, file, flags, mode ); if ( strcmp( file, "/vsh/theme/custom_theme.dat" ) == 0 && flags == ( PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC ) ) { t_record = arg->arg; log( "open %s flags %08x\ntheme file selected: %s\n", file, flags, selected_theme_file ); } return ret; }
/* * Allocate a system-call-entry-table for a resident library exporting * its functions via the SYSCALL_EXPORT technique. In order to allocate * such a table, we start at the object pointed to by g_pSysEntControl * (normally the top member of the initialSysEntTable linked list). * We scroll through that data structure until we find an object which * is not already being used and which is big enough to hold the amount * of exported functions. * * @param numEntry The amount of exported functions of a * resident library. * * Returns 0 on success. * */ s32 AllocSysTable(u16 numEntries) { SceSysCallEntryTable *sysTableEntry = NULL; SceSysCallEntryTable *newSysTableEntry = NULL; for (sysTableEntry = g_pSysEntControl; sysTableEntry; sysTableEntry = sysTableEntry->next) { if (sysTableEntry->inUse) continue; /* * Here, the concept "first fit" is used. We scan the list * for an unused sysEntryTable object big-enough to hold the * amount of exported functions. If the object is exactly * the size requested, its start address will be returned * and marked as being in-use. * * If the object can hold more than the requested numEntries, * split into two new blocks. The first block holds the exact * number of requested entries and its start address will be returned. * The second block will be unlinked from the free entry table stack. * It holds the remaining entries from the original block ready to be * used by another request. */ if (sysTableEntry->numEntries == numEntries) { //0x000004F4 sysTableEntry->inUse = SCE_TRUE; return sysTableEntry->startAddr; } /* * Example: We want to allocate a new SysEntryTable object capable * of holding 60 exported functions. * * State of the list before the object is allocated. * * +------------+ +------------+ * | A = 100 |-->| B = 150 |-->... * +------------+ +------------+ */ if (sysTableEntry->numEntries > numEntries) { //0x000004FC if (g_pFreeSysEnt == NULL) { newSysTableEntry = (SceSysCallEntryTable *)sceKernelAllocHeapMemory(g_loadCoreHeap(), sizeof(SceSysCallEntryTable)); } else { newSysTableEntry = g_pFreeSysEnt; //0x00000544 g_pFreeSysEnt = g_pFreeSysEnt->next; } newSysTableEntry->inUse = SCE_FALSE; //0x00000550 newSysTableEntry->startAddr = sysTableEntry->startAddr + numEntries; //0x0000055C newSysTableEntry->numEntries = sysTableEntry->numEntries - numEntries; newSysTableEntry->next = sysTableEntry->next; sysTableEntry->inUse = SCE_TRUE; //0x00000578 sysTableEntry->numEntries = numEntries; sysTableEntry->next = newSysTableEntry; /* * State of the list after the object is allocated. * * +------------+ +------------+ +------------+ * |###A = 60###|-->| A' = 40 |-->| B = 150 |-->... * +------------+ +------------+ +------------+ */ return sysTableEntry->startAddr; } } return SCE_ERROR_KERNEL_ERROR; }
int makeCxmbThemeFile( unsigned int cxmb_magic, const char * cxmb_theme_file ) { const char * folders_name[] = { "/data/cert", "/dic", "/font", "/kd", "/kd/resource", "/vsh/etc", "/vsh/module", "/vsh/resource" }; int folders_count = 8; const char * support_exts[] = { ".prx", ".rco", ".bmp", ".pmf", ".res", ".pgf", ".bwfon", ".rsc", ".dat", ".img", ".bin", ".cet", ".dic" }; int exts_count = 13; int dfd, heap_id, fd, i, bytes, file_count = 0; unsigned int ptf_h[5]; char path[128], file[128], preview[64]; u8 * buf; // dectect if theme file in conf exist int ctf = sceIoOpen( cxmb_theme_file, PSP_O_RDONLY, 0644 ); if ( ctf >= 0 ) { log( "theme file exist!\n" ); sceIoClose( ctf ); return 0; } dfd = sceIoDopen( "ms0:/cxmb" ); if ( dfd < 0 ) { log( "no cxmb folder found!\n" ); return 0; } sceIoDclose( dfd ); sprintf( preview, "ms0:/cxmb%s", &cxmb_theme_file[14] ); preview[strlen( preview ) - 3] = 'p'; log( "preview: %s\n", preview ); fd = sceIoOpen( preview, PSP_O_RDONLY, 0644 ); if ( fd < 0 ) { log( "no preview ptf file found!\n" ); return 0; } sceIoLseek( fd, 0x100, PSP_SEEK_SET ); sceIoRead( fd, ptf_h, 20 ); // create CXMB_MKCTF_BUF_SIZE + 32kb heap heap_id = sceKernelCreateHeap( 2, CXMB_MKCTF_BUF_SIZE + 1024 * 32 , 1, "cxmb_tmp_heap"); if ( heap_id < 0 ) { log( "failed in create heap in making cxmb theme file!\n" ); return -1; } CtfHeader * ch = ( CtfHeader * )sceKernelAllocHeapMemory( heap_id, sizeof( CtfHeader ) * 64 ); memset( ch, 0, sizeof( CtfHeader ) * 64 ); SceIoDirent * ent = ( SceIoDirent * )sceKernelAllocHeapMemory( heap_id, sizeof( SceIoDirent ) ); memset( ent, 0, sizeof( SceIoDirent ) ); sceIoMkdir( "ms0:/PSP/THEME", 0777 ); ctf = sceIoOpen( cxmb_theme_file, PSP_O_RDWR | PSP_O_CREAT | PSP_O_TRUNC, 0777 ); if ( ctf < 0 ) { log( "failed in opening %s\n", cxmb_theme_file ); sceKernelFreeHeapMemory( heap_id, ent ); sceKernelFreeHeapMemory( heap_id, ch ); sceKernelDeleteHeap( heap_id ); return -1; } else { if ( ptf_h[2] == 0 ) ptf_h[2] = sceIoLseek( fd, 0, PSP_SEEK_END ); log( "ptf sections size %08x\n", ptf_h[2] ); buf = sceKernelAllocHeapMemory( heap_id, ptf_h[2] ); if ( buf ) { sceIoLseek( fd, 0, PSP_SEEK_SET ); sceIoRead( fd, buf, ptf_h[2] ); sceIoWrite( ctf, buf, ptf_h[2] ); sceIoClose( fd ); sceKernelFreeHeapMemory( heap_id, buf ); sceIoLseek( ctf, 0x10, PSP_SEEK_SET ); sceIoWrite( ctf, &cxmb_magic, 4 ); sceIoLseek( ctf, 0x1C, PSP_SEEK_SET ); sceIoWrite( ctf, &ptf_h[2], 4 ); memset( &ptf_h[2], 0, 12 ); sceIoLseek( ctf, 0x100, PSP_SEEK_SET ); sceIoWrite( ctf, ptf_h, 20 ); sceIoLseek( ctf, 0, PSP_SEEK_END ); for ( i = 0; i < folders_count; i ++ ) { sprintf( path, "ms0:/cxmb%s", folders_name[i] ); dfd = sceIoDopen( path ); if ( dfd < 0 ) { log( "folder %s not found!\n", path ); continue; } log( "parsing %s\n", path ); while ( sceIoDread( dfd, ent ) > 0 ) { log( "found %s\n", ent->d_name ); if ( ( ent->d_stat.st_attr & FIO_SO_IFDIR ) || ent->d_name[0] == '.' ) { log( "ignore %s\n", ent->d_name ); continue; } if ( endwithistrs( ent->d_name, support_exts, exts_count ) ) { sprintf( file, "%s/%s", path, ent->d_name ); sprintf( ch[file_count].name, "%s/%s", folders_name[i], ent->d_name ); ch[file_count].start = sceIoLseek( ctf, 0, PSP_SEEK_CUR ); ch[file_count].size = 0; if ( cmpistrs( ent->d_name, diff_files, diff_count ) ) { char ori_file[128]; sprintf( ori_file, "%s/%s", CXMB_SUPPORT_FOLDER, ent->d_name ); ch[file_count].size = makeDiff( file, ori_file, heap_id, ctf ); } else { log( "dealing with %s\n", ent->d_name ); fd = sceIoOpen( file, PSP_O_RDONLY, 0644 ); if ( fd < 0 ) { log( "failed in opening %s\n", file ); continue; } buf = ( u8 * )sceKernelAllocHeapMemory( heap_id, CXMB_MKCTF_BUF_SIZE ); bytes = sceIoRead( fd, buf, CXMB_MKCTF_BUF_SIZE ); while( bytes > 0 ) { ch[file_count].size += sceIoWrite( ctf, buf, bytes ); bytes = sceIoRead( fd, buf, CXMB_MKCTF_BUF_SIZE ); } sceKernelFreeHeapMemory( heap_id, buf ); sceIoClose( fd ); } if ( ch[file_count].size > 0 && ch[file_count].size < CXMB_MAX_FILE_SIZE ) { log( "start: %08x size: %08x\n", ch[file_count].start, ch[file_count].size ); file_count ++; } } else { log( "ignore %s\n", ent->d_name ); } } sceIoDclose( dfd ); } } else { log( "failed in allocating %08x heap\n", ptf_h[2] ); } } log( "file_count: %d\n", file_count ); if ( file_count > 0 ) { u8 sha1[20]; sceKernelUtilsSha1Digest( ( u8 * )ch, sizeof( CtfHeader ) * file_count, sha1 ); sceIoWrite( ctf, ch, sizeof( CtfHeader ) * file_count ); sceIoLseek( ctf, 0x14, PSP_SEEK_SET ); sceIoWrite( ctf, &sha1[0], 4 ); sceIoWrite( ctf, &file_count, 4 ); sceIoClose( ctf ); } else { sceIoClose( ctf ); sceIoRemove( cxmb_theme_file ); } sceKernelFreeHeapMemory( heap_id, ent ); sceKernelFreeHeapMemory( heap_id, ch ); sceKernelDeleteHeap( heap_id ); return 0; }
int install_cxmb( void ) { int fd = sceIoOpen( CXMB_CONF_FILE, PSP_O_RDONLY, 0644 ); if ( fd < 0 ) { log( "no conf file found!\n" ); fd = sceIoOpen( CXMB_CONF_FILE, PSP_O_RDWR | PSP_O_CREAT | PSP_O_TRUNC, 0777 ); if ( fd < 0 ) { log( "failed in creating conf file!\n" ); return -1; } strcpy( theme_file, CXMB_DEFAULT_THEME ); sceIoWrite( fd, theme_file, strlen( theme_file ) + 1 ); } readLine( fd, theme_file, 64 ); if ( truncpath( theme_file, ".ctf" ) < 0 ) { if ( truncpath( theme_file, ".CTF" ) < 0 ) { strcpy( theme_file, CXMB_DEFAULT_THEME ); } } sceIoClose( fd ); if ( endwithistr( theme_file, "random.ctf" ) ) { log( "random\n" ); randomCtf( theme_file ); } sprintf( cxmb_theme_file, "ms0:%s", theme_file ); log( "Theme file: %s\n", theme_file ); #if _CXMB_LITE == 0 makeCxmbThemeFile( cxmb_magic, cxmb_theme_file ); #endif lflash_drv = findDriver( "flashfat" ); fatms_drv = findDriver( "fatms" ); if ( !lflash_drv || !fatms_drv ) return -1; msIoOpen = fatms_drv->funcs->IoOpen; msIoGetstat = fatms_drv->funcs->IoGetstat; IoOpen = lflash_drv->funcs->IoOpen; IoRead = lflash_drv->funcs->IoRead; IoLseek = lflash_drv->funcs->IoLseek; IoIoctl = lflash_drv->funcs->IoIoctl; IoClose = lflash_drv->funcs->IoClose; IoGetstat = lflash_drv->funcs->IoGetstat; int intr = sceKernelCpuSuspendIntr(); fatms_drv->funcs->IoOpen = msIoOpen_new; fatms_drv->funcs->IoGetstat = msIoGetstat_new; lflash_drv->funcs->IoOpen = IoOpen_new; lflash_drv->funcs->IoRead = IoRead_new; lflash_drv->funcs->IoLseek = IoLseek_new; lflash_drv->funcs->IoIoctl = IoIoctl_new; lflash_drv->funcs->IoClose = IoClose_new; lflash_drv->funcs->IoGetstat= IoGetstat_new; sceKernelCpuResumeIntr( intr ); sceKernelIcacheInvalidateAll(); sceKernelDcacheWritebackInvalidateAll(); sceIoOpen( "ms0:/dummy.prx", PSP_O_RDONLY, 0644 ); log( "redirected io_driver!\n" ); log( "ms_drv_arg: %08x\n", ( unsigned int )ms_drv ); previous = setStartModuleHandler( OnModuleStart ); log("startModuleHandler setup!\n"); fd = sceIoOpen( cxmb_theme_file, PSP_O_RDONLY, 0644 ); if ( fd < 0 ) { log( "no ctf file found!\n" ); return 0; } mem_id = sceKernelCreateHeap( 2, 1024 * 5 , 1, "cxmb_heap"); if ( mem_id < 0 ) { log( "failed in creating cxmb_heap!\n" ); sceIoClose( fd ); return -1; } unsigned int magic; sceIoLseek( fd, 0x10, PSP_SEEK_SET ); sceIoRead( fd, &magic, 4 ); if ( magic != cxmb_magic ) { log( "magic not match!\n" ); sceIoClose( fd ); return -1; } sceIoRead( fd, &ctf_sig, 4 ); sceIoRead( fd, &header_size, 4 ); log( "header size: %d\n", header_size ); ctf_header = sceKernelAllocHeapMemory( mem_id, sizeof( CtfHeader ) * header_size ); int offset = - sizeof( CtfHeader ) * header_size; sceIoLseek( fd, offset, PSP_SEEK_END ); sceIoRead( fd, ctf_header, sizeof( CtfHeader ) * header_size ); sceIoClose( fd ); log( "read ctf_header!\n" ); ctf_handler = sceKernelAllocHeapMemory( mem_id, sizeof( CtfHandler ) * 32 ); memset( ctf_handler, 0, sizeof( CtfHandler ) * 32 ); return 0; }