int inst_and_run_kernel_dynamic(uint8_t *payload, int size, uint64_t *residence) { if(!size) return -1; if(!payload) return -2; void *skprx=alloc(size, 0x27); if(skprx) { memcpy(skprx, get_secure_user_ptr(payload), size); f_desc_t f; int (* func)(void); f.addr = skprx; f.toc = (void *)MKA(TOC); func = (void *)&f; func(); uint64_t resident=(uint64_t)skprx; copy_to_user(&resident, get_secure_user_ptr(residence), 8); return 1; } return 0; }
int sys_psp_prx_patch(uint32_t *unk, uint8_t *elf_buf, void *link_register) { unk = get_secure_user_ptr(unk); elf_buf = get_secure_user_ptr(elf_buf); #ifdef DEBUG //DPRINTF("link_register = %p\n", link_register); if (link_register == (void *)(pemucorelib_base+prx_patch_call_lr)) { if (*(uint32_t *)&elf_buf[0] == 0x7F454C46) { Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; PspModuleInfo *modinfo; ehdr = (Elf32_Ehdr *)elf_buf; phdr = (Elf32_Phdr *)(elf_buf+swap32(ehdr->e_phoff)); modinfo = (PspModuleInfo *)(elf_buf+swap32(phdr[0].p_paddr)); DPRINTF("Module %s (elf_buf=%p)\n", modinfo->modname, elf_buf); } } #endif psp_func1(unk, elf_buf); return 0; }
int map_path_user(char *oldpath, char *newpath, uint32_t flags) { char *oldp, *newp; #ifdef DEBUG DPRINTF("map_path_user, called by process %s: %s -> %s\n", get_process_name(get_current_process_critical()), oldpath, newpath); #endif if (oldpath == 0) return -1; int ret = pathdup_from_user(get_secure_user_ptr(oldpath), &oldp); if (ret != 0) return ret; if (newpath == 0) newp = NULL; else { ret = pathdup_from_user(get_secure_user_ptr(newpath), &newp); if (ret != 0) { dealloc(oldp, 0x27); return ret; } } ret = map_path(oldp, newp, flags | FLAG_COPY); dealloc(oldp, 0x27); if (newp) dealloc(newp, 0x27); return ret; }
int sys_psp_read_umd(int unk, void *buf, uint64_t sector, uint64_t ofs, uint64_t size) { uint64_t offset, dummy; int ret; #ifdef DEBUG DPRINTF("umd read %lx %lx %lx\n", sector, ofs, size); #endif if (!mutex) { object_handle_t obj_handle; void *object_table = get_current_process()->object_table; int ret = open_kernel_object(object_table, *(uint32_t *)(emulator_api_base+umd_mutex_offset), (void **)&mutex, &obj_handle, SYS_MUTEX_OBJECT); if (ret != 0) { #ifdef DEBUG DPRINTF("Cannot open user mutex, using an own one\n"); #endif mutex_create(&mutex, SYNC_PRIORITY, SYNC_NOT_RECURSIVE); user_mutex = 0; } else { #ifdef DEBUG DPRINTF("user mutex opened succesfully\n"); #endif user_mutex = 1; close_kernel_object_handle(object_table, obj_handle); } } mutex_lock(mutex, 0); offset = sector*0x800; if (ofs != 0) { offset = offset+0x800-ofs; } ret = cellFsLseek(umd_fd, offset, SEEK_SET, &dummy); if (ret != 0) { mutex_unlock(mutex); return ret; } ret = cellFsRead(umd_fd, get_secure_user_ptr(buf), size, &dummy); mutex_unlock(mutex); if (ret == 0) ret = (int)size; return ret; }
int sys_psp_post_savedata_initstart(int result, void *param) { DPRINTF("Savedata init start\n"); if (result == 0) { savedata_param = get_secure_user_ptr(param); } return result; }
int sys_psp_post_savedata_initstart(int result, void *param) { #ifdef DEBUG DPRINTF("Savedata init start\n"); #endif if (result == 0) savedata_param = get_secure_user_ptr(param); return result; }
int sys_prx_load_vsh_plugin(unsigned int slot, char *path, void *arg, uint32_t arg_size) { #ifdef MAMBA_LOADER if (mamba_loaded == 1) return ECANCELED; //USE MAMBA INSTEAD TO LOAD THEM ! #endif if (!vsh_process) vsh_process = get_vsh_process(); if (!vsh_process) return ESRCH; void *kbuf, *vbuf; sys_prx_id_t prx; int ret; path = get_secure_user_ptr(path); arg = get_secure_user_ptr(arg); if (slot >= MAX_VSH_PLUGINS || (arg != NULL && arg_size > KB(64))) return EINVAL; if (vsh_plugins[slot] != 0) return EKRESOURCE; prx = prx_load_module(vsh_process, 0, 0, path); if (prx < 0) return prx; if (arg && arg_size > 0) { page_allocate_auto(vsh_process, KB(64), 0x2F, &kbuf); page_export_to_proc(vsh_process, kbuf, 0x40000, &vbuf); copy_from_user(arg, kbuf, arg_size); } else vbuf = NULL; ret = prx_start_module_with_thread(prx, vsh_process, 0, (uint64_t)vbuf); if (vbuf) { page_unexport_from_proc(vsh_process, vbuf); page_free(vsh_process, kbuf, 0x2F); } if (ret == 0) vsh_plugins[slot] = prx; else { prx_stop_module_with_thread(prx, vsh_process, 0, 0); prx_unload_module(prx, vsh_process); } return ret; }
int inst_and_run_kernel(uint8_t *payload, int size) { if((!size) || (size>0x10000)) return -1; if(!payload) return -2; memcpy((void *)0x80000000007f0000, get_secure_user_ptr(payload), size); f_desc_t f; int (* func)(void); f.addr = (void *)0x80000000007f0000; f.toc = (void *)MKA(TOC); func = (void *)&f; func(); return 0; }
int sys_psp_set_decrypt_options(int decrypt_patch, uint32_t tag, uint8_t *keys, uint8_t code, uint32_t tag2, uint8_t *keys2, uint8_t code2) { if (!umd_file) return EABORT; keys = get_secure_user_ptr(keys); if (keys) { if (copy_from_user(keys, psp_keys, 0x10) == 0) { psp_tag = tag; psp_code = code; condition_psp_keys = 1; } } condition_psp_dec = decrypt_patch; return 0; }
int sys_load_mamba(char *mamba_file) { if (mamba_loaded == 1) return ECANCELED; mamba_file = get_secure_user_ptr(mamba_file); CellFsStat stat; int ret = cellFsStat(mamba_file, &stat); if (ret == 0) { int fd; ret = cellFsOpen(mamba_file, CELL_FS_O_RDONLY, &fd, 0, NULL, 0); if (ret == 0) { uint32_t psize = stat.st_size; void *mamba = alloc(psize, 0x27); if (mamba) { uint64_t rs; ret = cellFsRead(fd, mamba, psize, &rs); cellFsClose(fd); if (ret != 0) { dealloc(mamba, 0x27); mamba = NULL; return ret; } mamba_loaded = 1; f_desc_t f; f.toc = (void *)MKA(TOC); int (* func)(void); f.addr = mamba; func = (void *)&f; func(); return 0; } return ENOMEM; } } return ret; }
int sys_write_cobra_config(CobraConfig *cfg) { int copy_size; cfg = get_secure_user_ptr(cfg); if (cfg->size > 4096) return EINVAL; check_and_correct(cfg); cfg->checksum = checksum(cfg); copy_size = cfg->size - sizeof(config.size); if (copy_size < 0) copy_size = 0; memcpy(&config.checksum, &cfg->checksum, copy_size); bd_video_region = config.bd_video_region; dvd_video_region = config.dvd_video_region; condition_ps2softemu = config.ps2softemu; return write_cobra_config(); }
int sys_read_cobra_config(CobraConfig *cfg) { int erase_size, copy_size; cfg = get_secure_user_ptr(cfg); if (cfg->size > 4096) return EINVAL; erase_size = cfg->size-sizeof(config.size); if (erase_size < 0) erase_size = 0; memset(&cfg->checksum, 0, erase_size); copy_size = ((cfg->size > config.size) ? config.size : cfg->size) - sizeof(config.size); if (copy_size < 0) copy_size = 0; ////DPRINTF("erase = %d, copy = %d\n", erase_size, copy_size); memcpy(&cfg->checksum, &config.checksum, copy_size); return 0; }
int sys_psp_set_umdfile(char *file, char *id, int prometheus) { if(vsh_offset == 0) return EINVAL; int ret; file = get_secure_user_ptr(file); id = get_secure_user_ptr(id); if (file == NULL) { if (umd_file) { dealloc(umd_file, 0x27); umd_file = NULL; } if (mutex) { if (user_mutex) { user_mutex = 0; } else { mutex_destroy(mutex); } mutex = NULL; } if (patches_backup) { #ifdef DEBUG DPRINTF("[PSP VSH PATCHES] Restore original data\n"); #endif for (int i = 0; patches_backup[i].offset != 0; i++) { lv1_pokew(patches_backup[i].offset, patches_backup[i].data); #ifdef DEBUG DPRINTF("%d) poke 0x%x at address 0x%x\n", i + 1, patches_backup[i].data, patches_backup[i].offset); #endif } dealloc(patches_backup, 0x27); patches_backup = NULL; } condition_psp_iso = 0; condition_psp_dec = 0; condition_psp_keys = 0; condition_psp_prometheus = 0; return 0; } strncpy(psp_id, id, 10); psp_id[10] = 0; if (strlen(psp_id) != 10) return EINVAL; ret = pathdup_from_user(file, &umd_file); if (ret != 0) return ret; condition_psp_iso = 1; condition_psp_prometheus = prometheus; #ifdef DEBUG if (prometheus) { DPRINTF("Using prometheus patch.\n"); } #endif if(get_psp_patches()) return EINVAL; if (!patches_backup) { patches_backup = alloc(sizeof(psp_drm_patches), 0x27); memcpy(patches_backup, &psp_drm_patches, sizeof(psp_drm_patches)); #ifdef DEBUG DPRINTF("Making patches..\n"); #endif for (int i = 0; psp_drm_patches[i].offset != 0; i++) { patches_backup[i].data = lv1_peekw(patches_backup[i].offset); lv1_pokew(psp_drm_patches[i].offset, psp_drm_patches[i].data); #ifdef DEBUG DPRINTF("Offset: 0x%08X | Poked Data: 0x%08X | Original Data: 0x%08X\n", (uint32_t)psp_drm_patches[i].offset, (uint32_t)psp_drm_patches[i].data, (uint32_t)patches_backup[i].data); #endif } } return 0; }
int sys_psp_read_header(int fd, char *buf, uint64_t nbytes, uint64_t *nread) { int ret; uint32_t n, unk2; uint64_t umd_size; sys_prx_id_t *list; uint32_t *unk; process_t process; #ifdef DEBUG DPRINTF("umd read header: %p %lx\n", buf, nbytes); #endif buf = get_secure_user_ptr(buf); nread = get_secure_user_ptr(nread); if (!umd_file || nbytes != 0x100) return EABORT; pemucorelib_base = 0; emulator_api_base = 0; list = alloc(SPRX_NUM*sizeof(sys_prx_module_info_t), 0x35); unk = alloc(SPRX_NUM*sizeof(uint32_t), 0x35); process = get_current_process(); ret = prx_get_module_list(process, list, unk, SPRX_NUM, &n, &unk2); if (ret == 0) { char *filename = alloc(256, 0x35); sys_prx_segment_info_t *segments = alloc(sizeof(sys_prx_segment_info_t), 0x35); for (int i = 0; i < SPRX_NUM; i++) { sys_prx_module_info_t modinfo; memset(&modinfo, 0, sizeof(sys_prx_module_info_t)); modinfo.filename_size = 256; modinfo.segments_num = 1; if (prx_get_module_info(process, list[i], &modinfo, filename, segments) == 0) { if (strstr(filename, "/emulator_api.sprx")) { emulator_api_base = segments[0].base; #ifdef DEBUG DPRINTF("emulator_api base = %08lx\n", emulator_api_base); #endif } else if (strstr(filename, "/PEmuCoreLib.sprx")) { pemucorelib_base = segments[0].base; #ifdef DEBUG DPRINTF("PEmuCoreLib base = %08lx\n", pemucorelib_base); #endif } } } if (pemucorelib_base == 0 || emulator_api_base == 0) ret = EABORT; dealloc(filename, 0x35); dealloc(segments, 0x35); } dealloc(list, 0x35); dealloc(unk, 0x35); if (ret != 0) return ret; ret = cellFsOpen(umd_file, CELL_FS_O_RDONLY, &umd_fd, 0, NULL, 0); if (ret != 0) return ret; cellFsLseek(umd_fd, 0, SEEK_END, &umd_size); // Fake header. We will write only values actually used memset(buf, 0, 0x100); *(uint32_t *)(buf+0x0c) = 0x10; *(uint32_t *)(buf+0x64) = (umd_size/0x800)-1; // Last sector of umd strncpy(buf+0x70, psp_id, 10); #ifdef DEBUG DPRINTF("ID: %s\n", psp_id); #endif if (mutex && user_mutex) { mutex = NULL; user_mutex = 0; } *nread = 0x100; return 0; }
static INLINE int sys_get_version2(uint16_t *version) { uint16_t cb = MAMBA_VERSION_BCD; return copy_to_user(&cb, get_secure_user_ptr(version), sizeof(uint16_t)); }
static INLINE int sys_get_version(uint32_t *version) { uint32_t pv = MAKE_VERSION(MAMBA_VERSION, FIRMWARE_VERSION, IS_CFW); return copy_to_user(&pv, get_secure_user_ptr(version), sizeof(uint32_t)); }
int sys_psp_set_umdfile(char *file, char *id, int prometheus) { int ret; file = get_secure_user_ptr(file); id = get_secure_user_ptr(id); if (file == NULL) { if (umd_file) { dealloc(umd_file, 0x27); umd_file = NULL; } if (mutex) { if (user_mutex) { user_mutex = 0; } else { mutex_destroy(mutex); } mutex = NULL; } if (patches_backup) { for (int i = 0; patches_backup[i].offset != 0; i++) { copy_to_process(vsh_process, &patches_backup[i].data, (void *)(uint64_t)(0x10000+patches_backup[i].offset), 4); } dealloc(patches_backup, 0x27); patches_backup = NULL; } condition_psp_iso = 0; condition_psp_dec = 0; condition_psp_keys = 0; condition_psp_prometheus = 0; return 0; } strncpy(psp_id, id, 10); psp_id[10] = 0; if (strlen(psp_id) != 10) return EINVAL; ret = pathdup_from_user(file, &umd_file); if (ret != 0) return ret; condition_psp_iso = 1; condition_psp_prometheus = prometheus; #ifdef DEBUG if (prometheus) { DPRINTF("Using prometheus patch.\n"); } #endif if (!patches_backup) { switch(vsh_check) { case VSH_HASH: DPRINTF("Now patching PSP DRM into spoofed DEBUG VSH..\n"); patches_backup = alloc(sizeof(psp_drm_patches), 0x27); memcpy(patches_backup, &psp_drm_patches, sizeof(psp_drm_patches)); for (int i = 0; psp_drm_patches[i].offset != 0; i++) { DPRINTF("Offset: 0x%08X | Data: 0x%08X\n", (uint32_t)psp_drm_patches[i].offset, (uint32_t)psp_drm_patches[i].data); copy_from_process(vsh_process, (void *)(uint64_t)(0x10000+patches_backup[i].offset), &patches_backup[i].data, 4); if (copy_to_process(vsh_process, &psp_drm_patches[i].data, (void *)(uint64_t)(0x10000+psp_drm_patches[i].offset), 4) != 0) { fatal("copy_to_process failed, you forgot to make spoofed DEBUG VSH text writable, retard!\n"); } } break; case VSH_NRM_HASH: DPRINTF("Now patching PSP DRM into normal DEBUG VSH..\n"); patches_backup = alloc(sizeof(psp_drm_patches), 0x27); memcpy(patches_backup, &psp_drm_patches, sizeof(psp_drm_patches)); for (int i = 0; psp_drm_patches[i].offset != 0; i++) { DPRINTF("Offset: 0x%08X | Data: 0x%08X\n", (uint32_t)psp_drm_patches[i].offset, (uint32_t)psp_drm_patches[i].data); copy_from_process(vsh_process, (void *)(uint64_t)(0x10000+patches_backup[i].offset), &patches_backup[i].data, 4); if (copy_to_process(vsh_process, &psp_drm_patches[i].data, (void *)(uint64_t)(0x10000+psp_drm_patches[i].offset), 4) != 0) { fatal("copy_to_process failed, you forgot to make normal DEBUG VSH text writable, retard!\n"); } } break; case VSH_CEX_HASH: DPRINTF("Now patching PSP DRM into spoofed RETAIL VSH..\n"); patches_backup = alloc(sizeof(cex_psp_drm_patches), 0x27); memcpy(patches_backup, &cex_psp_drm_patches, sizeof(cex_psp_drm_patches)); for (int i = 0; cex_psp_drm_patches[i].offset != 0; i++) { DPRINTF("Offset: 0x%08X | Data: 0x%08X\n", (uint32_t)cex_psp_drm_patches[i].offset, (uint32_t)cex_psp_drm_patches[i].data); copy_from_process(vsh_process, (void *)(uint64_t)(0x10000+patches_backup[i].offset), &patches_backup[i].data, 4); if (copy_to_process(vsh_process, &cex_psp_drm_patches[i].data, (void *)(uint64_t)(0x10000+cex_psp_drm_patches[i].offset), 4) != 0) { fatal("copy_to_process failed, you forgot to make spoofed RETAIL VSH text writable, retard!\n"); } } break; default: DPRINTF("WARNING: Unknown VSH loaded.\n Cannot patch PSP DRM into vsh.self\n"); break; } } return 0; }
int sys_psp_set_umdfile(char *file, char *id, int prometheus) { int ret; file = get_secure_user_ptr(file); id = get_secure_user_ptr(id); if (file == NULL) { if (umd_file) { dealloc(umd_file, 0x27); umd_file = NULL; } if (mutex) { if (user_mutex) user_mutex = 0; else mutex_destroy(mutex); mutex = NULL; } if (patches_backup) { for (int i = 0; patches_backup[i].offset != 0; i++) copy_to_process(vsh_process, &patches_backup[i].data, (void *)(uint64_t)(0x10000+patches_backup[i].offset), 4); dealloc(patches_backup, 0x27); patches_backup = NULL; } condition_psp_iso = 0; condition_psp_dec = 0; condition_psp_keys = 0; condition_psp_prometheus = 0; return 0; } strncpy(psp_id, id, 10); psp_id[10] = 0; if (strlen(psp_id) != 10) return EINVAL; ret = pathdup_from_user(file, &umd_file); if (ret != 0) return ret; condition_psp_iso = 1; condition_psp_prometheus = prometheus; #ifdef DEBUG if (prometheus) DPRINTF("Using prometheus patch.\n"); #endif if (!patches_backup) { switch(vsh_check) { case VSH_HASH: #ifdef DEBUG DPRINTF("Now patching PSP DRM In Retail VSH..\n"); #endif patches_backup = alloc(sizeof(psp_drm_patches), 0x27); memcpy(patches_backup, &psp_drm_patches, sizeof(psp_drm_patches)); for (int i = 0; psp_drm_patches[i].offset != 0; i++) { #ifdef DEBUG DPRINTF("Offset: 0x%08X | Data: 0x%08X\n", (uint32_t)psp_drm_patches[i].offset, (uint32_t)psp_drm_patches[i].data); #endif copy_from_process(vsh_process, (void *)(uint64_t)(0x10000+patches_backup[i].offset), &patches_backup[i].data, 4); if (copy_to_process(vsh_process, &psp_drm_patches[i].data, (void *)(uint64_t)(0x10000+psp_drm_patches[i].offset), 4) != 0) fatal("copy_to_process failed, you forgot to make vsh text writable, retard!\n"); } break; default: #ifdef DEBUG DPRINTF("Unknown VSH HASH, PSP DRM was not patched!\n"); #endif break; } } return 0; }