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; }
void uninstall_cxmb() { //free the cxmb heap sceKernelFreeHeapMemory( mem_id, ctf_handler ); sceKernelFreeHeapMemory( mem_id, ctf_header ); sceKernelDeleteHeap( mem_id ); ctf_handler = NULL; ctf_header = NULL; }
int makeDiff( const char * file, const char * ori, int heap_id, int ctf ) { log( "detect %s, start to make diff!\n", file ); u8 * buf = NULL, * buf_ori = NULL; int bytes = readPrx( file, heap_id, &buf ); if ( bytes < 0 ) { log( "failed in read %s!\n", file ); return -1; } if ( readPrx( ori, heap_id, &buf_ori ) != bytes ) { log( "failed in read %s!\n", ori ); sceKernelFreeHeapMemory( heap_id, buf ); sceKernelFreeHeapMemory( heap_id, buf_ori ); return -1; } int sub = ( strstr( file, diff_files[1] ) ? 0xA0: 0xC0 ); int diff_count = 0; unsigned int offset = 0, rec_attr[2]; int rec = 0; memset( rec_attr, 0, 8 ); while( offset < bytes ) { if ( buf[offset] != buf_ori[offset] ) { if ( !rec ) { rec_attr[0] = offset - sub; rec_attr[1] = 0; rec = 1; } rec_attr[1] ++; } else { if ( rec ) { log( "diff_start: %08x\nsize: %08x\n", rec_attr[0], rec_attr[1] ); sceIoWrite( ctf, rec_attr, 8 ); sceIoWrite( ctf, &buf[rec_attr[0] + sub], rec_attr[1] ); diff_count ++; rec = 0; } } offset ++; } sceKernelFreeHeapMemory( heap_id, buf_ori ); sceKernelFreeHeapMemory( heap_id, buf ); return diff_count; }
/* * 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; }
/* * FreeSysTable * * Free a system-call-entry-table of a resident library. In order * to free 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 the location * of the to-be-freed table is found and integrate it properly into * the list again, merging it with another free neighbor table if * needed. * * @param sysTableEntryAddr The address of an allocated SceSysCallEntryTable * object. * * Returns the address of the freed table on success. */ SceSysCallEntryTable *FreeSysTable(u32 sysTableEntryAddr) { SceSysCallEntryTable *curSysTableEntry = NULL; SceSysCallEntryTable *prevSysTableEntry = NULL; SceSysCallEntryTable *nextSysTableEntry = NULL; if (g_pSysEntControl == NULL) //0x000005D4 return NULL; //0x000005DC - 0x000005F4 /* Search for the location of the to-be-freed table. */ for (curSysTableEntry = g_pSysEntControl; curSysTableEntry != NULL && curSysTableEntry->startAddr != sysTableEntryAddr; curSysTableEntry = curSysTableEntry->next) prevSysTableEntry = curSysTableEntry; if (curSysTableEntry == NULL || curSysTableEntry->inUse == SCE_FALSE) //0x00000614 & 0x00000624 return NULL; /* Once found, mark it as being unused. */ curSysTableEntry->inUse = SCE_FALSE; //0x00000630 & 0x00000638 /* * If the previous system-call-entry-table is currently being * unused, merge these two tables together. Integrate the freed * table back into the list of currently free system call * entry-tables if it was unlinked from it during allocation process. */ if (prevSysTableEntry != NULL && prevSysTableEntry->inUse == SCE_FALSE) { //0x00000634 prevSysTableEntry->numEntries += curSysTableEntry->numEntries; //0x0000065C & 0x00000664 prevSysTableEntry->next = curSysTableEntry->next; //0x0000066C if (curSysTableEntry >= &initialSysEntTable[0] && curSysTableEntry <= &initialSysEntTable[TOP_SYSCALL_ENTRY_TABLE]) { //0x00000668 & 0x00000678 curSysTableEntry->next = g_pFreeSysEnt; //0x00000688 g_pFreeSysEnt = curSysTableEntry; //0x0000068C curSysTableEntry = prevSysTableEntry; //0x00000690 } else { sceKernelFreeHeapMemory(g_loadCoreHeap(), curSysTableEntry); //0x00000730 curSysTableEntry = prevSysTableEntry; } } /* * If both the previous table and the next table are used, * or the specified table is the last element and its * previous table is being used, don't merge it. */ if (curSysTableEntry->next == NULL || curSysTableEntry->next->inUse) //0x00000698 - 0x000006A4 return curSysTableEntry; /* * Here, we merge the upper (next) free system call table with the * specified table by the user. */ nextSysTableEntry = curSysTableEntry->next; //0x00000694 curSysTableEntry->numEntries += nextSysTableEntry->numEntries; //0x000006BC & 0x000006C4 curSysTableEntry->next = nextSysTableEntry->next; //0x000006CC if (nextSysTableEntry >= &initialSysEntTable[0] && nextSysTableEntry <= &initialSysEntTable[TOP_SYSCALL_ENTRY_TABLE]) { //0x000006C8 & 0x000006D8 nextSysTableEntry->next = g_pFreeSysEnt; //0x000006E8 g_pFreeSysEnt = nextSysTableEntry; } else { sceKernelFreeHeapMemory(g_loadCoreHeap(), nextSysTableEntry); //0x0000070C } return curSysTableEntry; }
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; }