diff --git a/CMakeLists.txt b/CMakeLists.txt index af92fb5..fe46107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,22 +17,22 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") add_executable(vmass src/main.c src/vmass.c + src/vmass_sysevent.c src/fat.c ) target_link_libraries(vmass SceCpuForDriver_stub - SceCtrlForDriver_stub SceDebugForDriver_stub SceDmacmgrForDriver_stub SceDisplayForDriver_stub SceIofilemgrForDriver_stub SceThreadmgrForDriver_stub SceModulemgrForDriver_stub + SceSysconForDriver_stub SceSysmemForDriver_stub SceSysclibForDriver_stub SceKernelSuspendForDriver_stub - taihenForKernel_stub ) set_target_properties(vmass diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..9e8fdf2 --- /dev/null +++ b/build.sh @@ -0,0 +1,9 @@ + +if [ ! -d build ]; then + mkdir build +fi + +cd build +cmake ../ +make +cd .. diff --git a/exports.yml b/exports.yml index c232446..bb6fe99 100644 --- a/exports.yml +++ b/exports.yml @@ -1,15 +1,18 @@ vmass: - attributes: 0 + attributes: 7 version: major: 0x1 - minor: 0x31 + minor: 0x40 main: start: module_start - stop: module_stop modules: - VmassForDriver: + SceUsbMassForDriver: syscall: false + nid: 0x15243EC5 functions: - - vmassGetDevInfo - - vmassReadSector - - vmassWriteSector + - vmassGetDevInfo: 0xD989A9F6 + - vmassReadSector: 0xB80D1DF8 + - vmassWriteSector: 0x081CA197 + - sceUsbMassIntrHandler: 0xF2BAB182 + - SceUsbMassForDriver_3C821E99: 0x3C821E99 + - SceUsbMassForDriver_7833D935: 0x7833D935 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 369069d..46125ce 100644 --- a/src/main.c +++ b/src/main.c @@ -16,84 +16,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include #include "vmass.h" -#define HookExport(module_name, library_nid, func_nid, func_name) taiHookFunctionExportForKernel(0x10005, &func_name ## _ref, module_name, library_nid, func_nid, func_name ## _patch) -#define HookImport(module_name, library_nid, func_nid, func_name) taiHookFunctionImportForKernel(0x10005, &func_name ## _ref, module_name, library_nid, func_nid, func_name ## _patch) -#define HookOffset(modid, offset, thumb, func_name) taiHookFunctionOffsetForKernel(0x10005, &func_name ## _ref, modid, 0, offset, thumb, func_name ## _patch) - -#define HookRelease(hook_uid, hook_func_name) ({ \ - (hook_uid > 0) ? taiHookReleaseForKernel(hook_uid, hook_func_name ## _ref) : -1; \ -}) - -#define GetExport(modname, lib_nid, func_nid, func) module_get_export_func(KERNEL_PID, modname, lib_nid, func_nid, (uintptr_t *)func) - -int module_get_export_func(SceUID pid, const char *modname, uint32_t lib_nid, uint32_t func_nid, uintptr_t *func); - -SceUID hook[6]; - -tai_hook_ref_t sceUsbMassGetDevInfo_ref; -tai_hook_ref_t sceUsbMassWriteSector_ref; -tai_hook_ref_t sceUsbMassReadSector_ref; -tai_hook_ref_t sceUsbMassIntrHandler_ref; -tai_hook_ref_t SceUsbMassForDriver_3C821E99_ref; -tai_hook_ref_t SceUsbMassForDriver_7833D935_ref; - -int sceUsbMassGetDevInfo_patch(SceUsbMassDevInfo *info){ - return vmassGetDevInfo(info); -} - -int sceUsbMassWriteSector_patch(SceSize sector_pos, const void *data, SceSize sector_num){ - return vmassWriteSector(sector_pos, data, sector_num); -} - -int sceUsbMassReadSector_patch(SceSize sector_pos, void *data, SceSize sector_num){ - return vmassReadSector(sector_pos, data, sector_num); -} - -int sceUsbMassIntrHandler_patch(int intr_code, void *userCtx){ - - if(intr_code != 0xF) - return 0x80010016; - - return -1; -} - -int SceUsbMassForDriver_3C821E99_patch(int a1, int a2){ - - if(a1 != 0xF) - return 0x80010016; - - return 0; -} - -int SceUsbMassForDriver_7833D935_patch(int a1, int a2){ - - if(a1 != 0xF) - return 0x80010016; - - return 0; -} - -tai_hook_ref_t ksceIoOpen_ref; -SceUID ksceIoOpen_patch(const char *file, int flags, SceMode mode){ - - SceUID fd; - - fd = TAI_CONTINUE(SceUID, ksceIoOpen_ref, file, flags, mode); - - if((fd > 0) && (strcmp(file, "tty0:") == 0 || strcmp(file, "tty1:") == 0 || strcmp(file, "tty7:") == 0)){ - ksceIoClose(fd); - fd = TAI_CONTINUE(SceUID, ksceIoOpen_ref, "uma0:log.txt", SCE_O_WRONLY | SCE_O_RDONLY | SCE_O_CREAT | SCE_O_APPEND, 0666); - } - - return fd; -} - void _start() __attribute__ ((weak, alias("module_start"))); int module_start(SceSize args, void *argp){ @@ -121,23 +47,7 @@ int module_start(SceSize args, void *argp){ ksceKernelFreeHeapMemory(0x1000B, data); - hook[0] = HookImport("SceSdstor", 0x15243ec5, 0xd989a9f6, sceUsbMassGetDevInfo); - hook[1] = HookImport("SceSdstor", 0x15243ec5, 0xb80d1df8, sceUsbMassReadSector); - hook[2] = HookImport("SceSdstor", 0x15243ec5, 0x081ca197, sceUsbMassWriteSector); - hook[3] = HookImport("SceSdstor", 0x15243ec5, 0xf2bab182, sceUsbMassIntrHandler); - hook[4] = HookImport("SceSdstor", 0x15243ec5, 0x3c821e99, SceUsbMassForDriver_3C821E99); - hook[5] = HookImport("SceSdstor", 0x15243ec5, 0x7833d935, SceUsbMassForDriver_7833D935); - ksceIoMount(0xF00, NULL, 2, 0, 0, 0); - /* - * redirect sceClibPrintf out to uma0:log.txt - */ - // HookImport("SceProcessmgr", 0x40fd29c7, 0x75192972, ksceIoOpen); - return SCE_KERNEL_START_SUCCESS; } - -int module_stop(SceSize args, void *argp){ - return SCE_KERNEL_STOP_CANCEL; -} diff --git a/src/sysevent.h b/src/sysevent.h new file mode 100644 index 0000000..76ce15b --- /dev/null +++ b/src/sysevent.h @@ -0,0 +1,28 @@ +/** + * \kernelgroup{SceSysEvent} + * \usage{psp2kern/kernel/sysevent.h,SceKernelSuspendForDriver_stub} + */ + +#ifndef _PSP2_KERNEL_SYSEVENT_H_ +#define _PSP2_KERNEL_SYSEVENT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (* SceSysEventCallback)(int resume, int eventid, void *args, void *opt); + +SceUID ksceKernelRegisterSysEventHandler(const char *name, SceSysEventCallback cb, void *argp); +int ksceKernelUnregisterSysEventHandler(SceUID id); + +#define SCE_SYS_EVENT_STATE_SUSPEND (0) +#define SCE_SYS_EVENT_STATE_POWEROFF (1) +#define SCE_SYS_EVENT_STATE_REBOOT (2) + +#ifdef __cplusplus +} +#endif + +#endif /* _PSP2_KERNEL_SYSEVENT_H_ */ diff --git a/src/vmass.c b/src/vmass.c index 7141ca2..c517b0b 100644 --- a/src/vmass.c +++ b/src/vmass.c @@ -16,33 +16,16 @@ #include #include #include +#include +#include #include #include -#include -#include #include -#include -#include +#include "sysevent.h" #include "vmass.h" +#include "vmass_sysevent.h" #include "fat.h" -typedef int (* SceSysEventCallback)(int resume, int eventid, void *args, void *opt); - -SceUID ksceKernelRegisterSysEventHandler(const char *name, SceSysEventCallback cb, void *argp); -int ksceKernelUnregisterSysEventHandler(SceUID id); - -#define SCE_SYS_EVENT_STATE_SUSPEND (0) -#define SCE_SYS_EVENT_STATE_POWEROFF (1) -#define SCE_SYS_EVENT_STATE_REBOOT (2) - -const char umass_start_byepass_patch[] = { - 0x00, 0xBF, 0x00, 0xBF, - 0x00, 0xBF, - 0x00, 0xBF, 0x00, 0xBF, - 0x00, 0xBF, - 0x00, 0x20, 0x00, 0x00 -}; - #define SIZE_2MiB 0x200000 #define SIZE_4MiB 0x400000 #define SIZE_10MiB 0xA00000 @@ -113,7 +96,7 @@ int _vmassReadSector(SceSize sector_pos, void *data, SceSize sector_num){ int page_idx = 0; SceSize off = (sector_pos << 9), size = (sector_num << 9), work_size; - if((size == 0) || ((off + size) > g_vmass_size) || (off >= g_vmass_size) || (size > g_vmass_size)) + if(((size - 1) > g_vmass_size) || (off >= g_vmass_size) || ((off + size) > g_vmass_size)) return -1; while(off >= page_alloc_list[page_idx].size){ @@ -150,7 +133,7 @@ int _vmassWriteSector(SceSize sector_pos, const void *data, SceSize sector_num){ int page_idx = 0; SceSize off = (sector_pos << 9), size = (sector_num << 9), work_size; - if((size == 0) || ((off + size) > g_vmass_size) || (off >= g_vmass_size) || (size > g_vmass_size)) + if(((size - 1) > g_vmass_size) || (off >= g_vmass_size) || ((off + size) > g_vmass_size)) return -1; while(off >= page_alloc_list[page_idx].size){ @@ -263,6 +246,9 @@ int getBytePerSecond(int time, int byte, int *dst){ #endif +#define VMASS_RW_THREAD_PRIORITY_DEF (0x6E) +#define VMASS_RW_THREAD_PRIORITY_WRK (0x28) + #define VMASS_REQ_READ (1 << 0) #define VMASS_REQ_WRITE (1 << 1) #define VMASS_REQ_DONE (1 << 30) @@ -276,37 +262,29 @@ SceUID thid, evf_id; int sceVmassRWThread(SceSize args, void *argp){ - int res, prev_priority; + int res; unsigned int opcode; + SceUID thid = ksceKernelGetThreadId(); + while(1){ + ksceKernelChangeThreadPriority(thid, VMASS_RW_THREAD_PRIORITY_DEF); + opcode = 0; res = ksceKernelWaitEventFlag(evf_id, VMASS_REQ_READ | VMASS_REQ_WRITE | VMASS_REQ_EXIT, SCE_EVENT_WAITOR | SCE_EVENT_WAITCLEAR_PAT, &opcode, NULL); if(res < 0) continue; - if(opcode == VMASS_REQ_READ){ - - prev_priority = ksceKernelGetThreadCurrentPriority(); - - ksceKernelChangeThreadPriority(ksceKernelGetThreadId(), 0x28); + ksceKernelChangeThreadPriority(thid, VMASS_RW_THREAD_PRIORITY_WRK); + if(opcode == VMASS_REQ_READ){ _vmassReadSector(g_sector_pos, g_pDataForRead, g_sector_num); ksceKernelSetEventFlag(evf_id, VMASS_REQ_DONE); - ksceKernelChangeThreadPriority(ksceKernelGetThreadId(), prev_priority); - }else if(opcode == VMASS_REQ_WRITE){ - - prev_priority = ksceKernelGetThreadCurrentPriority(); - - ksceKernelChangeThreadPriority(ksceKernelGetThreadId(), 0x28); - _vmassWriteSector(g_sector_pos, g_pDataForWrite, g_sector_num); ksceKernelSetEventFlag(evf_id, VMASS_REQ_DONE); - ksceKernelChangeThreadPriority(ksceKernelGetThreadId(), prev_priority); - }else if(opcode == VMASS_REQ_EXIT){ ksceKernelSetEventFlag(evf_id, VMASS_REQ_DONE); break; @@ -322,7 +300,7 @@ int vmassReadSector(SceSize sector_pos, void *data, SceSize sector_num){ SceSize off = (sector_pos << 9), size = (sector_num << 9); - if((size == 0) || ((off + size) > g_vmass_size) || (off >= g_vmass_size) || (size > g_vmass_size)) + if(((size - 1) > g_vmass_size) || (off >= g_vmass_size) || ((off + size) > g_vmass_size)) return -1; ksceKernelLockFastMutex(&lw_mtx); @@ -357,7 +335,7 @@ int vmassWriteSector(SceSize sector_pos, const void *data, SceSize sector_num){ SceSize off = (sector_pos << 9), size = (sector_num << 9); - if((size == 0) || ((off + size) > g_vmass_size) || (off >= g_vmass_size) || (size > g_vmass_size)) + if(((size - 1) > g_vmass_size) || (off >= g_vmass_size) || ((off + size) > g_vmass_size)) return -1; ksceKernelLockFastMutex(&lw_mtx); @@ -386,27 +364,28 @@ int vmassWriteSector(SceSize sector_pos, const void *data, SceSize sector_num){ return res; } -// Load umass.skprx to avoid taiHEN's unlinked problem -int load_umass(void){ +int sceUsbMassIntrHandler(int intr_code, void *userCtx){ - int res; - SceUID umass_modid, patch_uid; + if(intr_code != 0xF) + return 0x80010016; + + return -1; +} - // Since bootimage cannot be mounted after the second time, load vitashell's umass.skprx - umass_modid = ksceKernelLoadModule("ux0:VitaShell/module/umass.skprx", 0, NULL); - if(umass_modid < 0) - return umass_modid; +int SceUsbMassForDriver_3C821E99(int a1, int a2){ - patch_uid = taiInjectDataForKernel(0x10005, umass_modid, 0, 0x1546, umass_start_byepass_patch, sizeof(umass_start_byepass_patch) - 2); + if(a1 != 0xF) + return 0x80010016; - int start_res = -1; - res = ksceKernelStartModule(umass_modid, 0, NULL, 0, NULL, &start_res); - if(res >= 0) - res = start_res; + return 0; +} - taiInjectReleaseForKernel(patch_uid); +int SceUsbMassForDriver_7833D935(int a1, int a2){ - return res; + if(a1 != 0xF) + return 0x80010016; + + return 0; } int vmassFreeStoragePage(void){ @@ -426,15 +405,15 @@ int vmassAllocStoragePage(void){ SceUID memid; SceKernelAllocMemBlockKernelOpt opt, *pOpt; + memset(&opt, 0, sizeof(opt)); + opt.size = sizeof(opt); + opt.attr = SCE_KERNEL_ALLOC_MEMBLOCK_ATTR_HAS_PADDR; for(int i=0;i= SIZE_16MiB){ - buf[0] = 0xFFFFFFF8; setFat16Header(&fat_header, g_vmass_size >> 9); }else{ - buf[0] = 0xFFFFF8; setFat12Header(&fat_header, g_vmass_size >> 9); @@ -575,29 +552,6 @@ int vmassCreateImage(void){ return res; } -int sysevent_handler(int resume, int eventid, void *args, void *opt){ - - if(resume == 0 && eventid == 0x204 && *(int *)(args + 0x00) == 0x18 && *(int *)(args + 0x04) != SCE_SYS_EVENT_STATE_SUSPEND){ - - SceCtrlData pad; - if(ksceCtrlPeekBufferPositive(0, &pad, 1) < 0) - goto end; - - if((pad.buttons & SCE_CTRL_START) == 0) - goto end; - - /* - * Unmount uma0: and remove file cache etc. - */ - ksceIoUmount(0xF00, 1, 0, 0); - - vmassCreateImage(); - } - -end: - return 0; -} - int vmassInit(void){ int res; @@ -622,7 +576,7 @@ int vmassInit(void){ if(res < 0) goto del_thread; - sysevent_id = ksceKernelRegisterSysEventHandler("SceSysEventVmass", sysevent_handler, NULL); + sysevent_id = ksceKernelRegisterSysEventHandler("SceSysEventVmass", vmassSysEventHandler, NULL); if(sysevent_id < 0){ res = sysevent_id; goto del_thread; @@ -639,10 +593,6 @@ int vmassInit(void){ if(res < 0) goto free_storage_page; - res = load_umass(); - if(res < 0) - goto free_storage_page; - end: return res; diff --git a/src/vmass.h b/src/vmass.h index 7523908..08fce77 100644 --- a/src/vmass.h +++ b/src/vmass.h @@ -28,6 +28,9 @@ typedef struct SceUsbMassDevInfo { int vmassInit(void); +int vmassCreateImage(void); +int vmassLoadImage(void); + int vmassGetDevInfo(SceUsbMassDevInfo *info); int vmassReadSector(SceSize sector_pos, void *data, SceSize sector_num); int vmassWriteSector(SceSize sector_pos, const void *data, SceSize sector_num); diff --git a/src/vmass_sysevent.c b/src/vmass_sysevent.c new file mode 100644 index 0000000..7b964b6 --- /dev/null +++ b/src/vmass_sysevent.c @@ -0,0 +1,42 @@ +/* + * PlayStation(R)Vita Virtual Mass SysEvent Handler + * Copyright (C) 2021 Princess of Slepping + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "sysevent.h" +#include "vmass.h" + +int vmassSysEventHandler(int resume, int eventid, void *args, void *opt){ + + if(resume == 0 && eventid == 0x204 && *(int *)(args + 0x00) == 0x18 && *(int *)(args + 0x04) != SCE_SYS_EVENT_STATE_SUSPEND){ + + SceUInt32 ctrl = ~0x74FFFFFF; + + ksceSysconGetControlsInfo(&ctrl); + + if((~ctrl & SCE_SYSCON_CTRL_START) != 0){ + + /* + * Unmount uma0: and remove file cache etc. + */ + ksceIoUmount(0xF00, 1, 0, 0); + + vmassCreateImage(); + } + } + + return 0; +} diff --git a/src/vmass_sysevent.h b/src/vmass_sysevent.h new file mode 100644 index 0000000..f3efb81 --- /dev/null +++ b/src/vmass_sysevent.h @@ -0,0 +1,21 @@ +/* + * PlayStation(R)Vita Virtual Mass SysEvemt Handler Header + * Copyright (C) 2021 Princess of Slepping + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _VMASS_SYSEVENT_H_ +#define _VMASS_SYSEVENT_H_ + +int vmassSysEventHandler(int resume, int eventid, void *args, void *opt); + +#endif /* _VMASS_SYSEVENT_H_ */