diff --git a/Makefile b/Makefile index c7d8b47..89a151c 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ CFLAGS += -DDEBUG=$(DEBUG) endif LDFLAGS = -nostartfiles -L . -LIBS = -lpspsystemctrl_kernel +LIBS = -lpspsystemctrl_kernel -lpspumd PSP_FW_VERSION = 660 diff --git a/exports.exp b/exports.exp index 646ee62..08c2230 100644 --- a/exports.exp +++ b/exports.exp @@ -7,7 +7,7 @@ PSP_EXPORT_FUNC_HASH(module_stop) PSP_EXPORT_VAR_HASH(module_info) PSP_EXPORT_END -# Voluntary collision with Inferno to prevent conflicts +# Voluntary collision with Inferno to prevent loading PSP_EXPORT_START(inferno_driver, 0x0011, 0x0001) # inferno_driver_CF8299BE PSP_EXPORT_FUNC(infernoSetDiscType) @@ -19,4 +19,9 @@ PSP_EXPORT_FUNC(infernoCacheInit) PSP_EXPORT_FUNC(infernoSetUmdDelay) PSP_EXPORT_END +PSP_EXPORT_START(umd_livepatch, 0x0011, 0x0001) +PSP_EXPORT_FUNC(lp_discChangeCallback) +PSP_EXPORT_FUNC(lp_discChangeWatcher) +PSP_EXPORT_END + PSP_END_EXPORTS diff --git a/io_funcs.c b/io_funcs.c index 1374cd3..f1d0437 100644 --- a/io_funcs.c +++ b/io_funcs.c @@ -67,7 +67,7 @@ _impl_lp_readDiscHeader(PspIoDrvFileArg *arg, const char *devname) .byte_size_last = 0 }; - ret = reserveUmdFuncs.IoDevctl(arg, devname, lp_UmdIoctl_READ_SECTORS, + ret = reserveUmdFuncs.IoDevctl(arg, devname, lp_UmdDevctl_READ_SECTORS, ¶m, sizeof param, &hdr, ISO_SECTOR_SIZE); return ret; } @@ -116,10 +116,10 @@ patched_IoDevctl(PspIoDrvFileArg *arg, const char *devname, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen) { - switch ((lp_UmdIoctl) cmd) { - case lp_UmdIoctl_READ_GENERAL: - case lp_UmdIoctl_READ_CACHE: - case lp_UmdIoctl_READ_SECTORS: + switch ((lp_UmdDevctl) cmd) { + case lp_UmdDevctl_READ_GENERAL: + case lp_UmdDevctl_READ_CACHE: + case lp_UmdDevctl_READ_SECTORS: return _impl_lp_devctlRead(arg, devname, cmd, (lp_UmdLba *) indata, inlen, outdata, outlen); default: @@ -130,4 +130,25 @@ passthru: return reserveUmdFuncs.IoDevctl(arg, devname, cmd, indata, inlen, outdata, outlen); } + +int +patched_IoRead(PspIoDrvFileArg *arg, char *data, int len) +{ + Kprintf("Reading UMD data, hum dee dum...\n"); + return reserveUmdFuncs.IoRead(arg, data, len); +} + +int +patched_IoOpen(PspIoDrvFileArg *arg, char *file, int flags, SceMode mode) +{ + Kprintf("Opening UMD.\n"); + return reserveUmdFuncs.IoOpen(arg, file, flags, mode); +} + +void +lp_pingDiscRemoved(void) +{ + first_read = 1; +} + // vim: ft=c.doxygen diff --git a/io_funcs.h b/io_funcs.h index e1c20d2..d0845e1 100644 --- a/io_funcs.h +++ b/io_funcs.h @@ -28,32 +28,39 @@ */ typedef enum: int { - lp_UmdIoctl_01F00003 = 0x01F00003, - lp_UmdIoctl_01F010DB = 0x01F010DB, - - lp_UmdIoctl_DISC_TYPE = 0x01F20001, - lp_UmdIoctl_SEEK_RAW = 0x01F100A3, - lp_UmdIoctl_CACHE_ADD = 0x01F100A4, - lp_UmdIoctl_CACHE_ADD2 = 0x01F300A5, - - /* Cache control, worth intercepting */ - lp_UmdIoctl_01F300A7 = 0x01F300A7, - lp_UmdIoctl_01F300A8 = 0x01F300A8, - lp_UmdIoctl_01F300A9 = 0x01F300A9, - lp_UmdIoctl_NUM_SECTORS = 0x01F20002, - lp_UmdIoctl_NUM_SECTORS2 = 0x01F20003, - lp_UmdIoctl_01E18030 = 0x01E18030, - lp_UmdIoctl_01E180D3 = 0x01E180D3, - lp_UmdIoctl_01E080A8 = 0x01E080A8, - lp_UmdIoctl_GET_SECTOR_BUF = 0x01E28035, - lp_UmdIoctl_GET_SECTOR_SIZE = 0x01E280A9, - lp_UmdIoctl_01E38034 = 0x01E38034, - lp_UmdIoctl_READ_GENERAL = 0x01E380C0, - lp_UmdIoctl_READ_SECTORS = 0x01F200A1, - lp_UmdIoctl_READ_CACHE = 0x01F200A2, - lp_UmdIoctl_GET_INFO = 0x01E38012 + lp_UmdIoctl_01F010DB = 0x01F010DB, + lp_UmdIoctl_GET_OFFSET = 0x01D20001, + lp_UmdIoctl_LSEEK = 0x01F100A6, + lp_UmdIoctl_READ = 0x01F30003 } lp_UmdIoctl; +typedef enum: int { + lp_UmdDevctl_01F00003 = 0x01F00003, + lp_UmdDevctl_01F010DB = 0x01F010DB, + + lp_UmdDevctl_DISC_TYPE = 0x01F20001, + lp_UmdDevctl_SEEK_RAW = 0x01F100A3, + lp_UmdDevctl_CACHE_ADD = 0x01F100A4, + lp_UmdDevctl_CACHE_ADD2 = 0x01F300A5, + + /* CacDev control, worth intercepting */ + lp_UmdDevctl_01F300A7 = 0x01F300A7, + lp_UmdDevctl_01F300A8 = 0x01F300A8, + lp_UmdDevctl_01F300A9 = 0x01F300A9, + lp_UmdDevctl_NUM_SECTORS = 0x01F20002, + lp_UmdDevctl_NUM_SECTORS2 = 0x01F20003, + lp_UmdDevctl_01E18030 = 0x01E18030, + lp_UmdDevctl_01E180D3 = 0x01E180D3, + lp_UmdDevctl_01E080A8 = 0x01E080A8, + lp_UmdDevctl_GET_SECTOR_BUF = 0x01E28035, + lp_UmdDevctl_GET_SECTOR_SIZE = 0x01E280A9, + lp_UmdDevctl_01E38034 = 0x01E38034, + lp_UmdDevctl_READ_GENERAL = 0x01E380C0, + lp_UmdDevctl_READ_SECTORS = 0x01F200A1, + lp_UmdDevctl_READ_CACHE = 0x01F200A2, + lp_UmdDevctl_GET_INFO = 0x01E38012 +} lp_UmdDevctl; + typedef struct { int unknown1; // 0 int cmd; // 4 @@ -81,6 +88,23 @@ patched_IoDevctl(PspIoDrvFileArg *arg, const char *devname, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen); +int +patched_IoRead(PspIoDrvFileArg *arg, char *data, int len); + +int +patched_IoOpen(PspIoDrvFileArg *arg, char *file, int flags, SceMode mode); + +/** + * @brief Tell this module to expect a new disc. + * + * This function resets the "first read" flag which prompts this module to read + * the UMD's disc ID. + * On its own, this function does not invalidate the cache. It will only be + * invalidated if the effective disc ID has changed on the next read devctl. + */ +void +lp_pingDiscRemoved(void); + #endif //__IO_FUNCS_H // vim: ft=c.doxygen diff --git a/main.c b/main.c index 573b5bf..1220144 100644 --- a/main.c +++ b/main.c @@ -12,46 +12,61 @@ #include "io_funcs.h" #include +#include PSP_MODULE_INFO("umd_livepatch", PSP_MODULE_KERNEL, 2, 1); void lp_patchFunction(u32 addr, void *newaddr, void *fptr); +PspIoDrv *umdDriver; PspIoDrvFuncs reserveUmdFuncs; -PspIoDrvFuncs patchedUmdFuncs; - -PspIoDrv originalUmdDriver; - -PspIoDrv reserveUmdDriver = { - .name = "umdraw", - .dev_type = 4, - .unk2 = 0x800, - .name2 = "UMD_RAW", - .funcs = &reserveUmdFuncs -}; - -PspIoDrv patchedUmdDriver = { - .name = "umd", - .dev_type = 4, // block device - .unk2 = 0x800, - .name2 = "UMD9660", - .funcs = &patchedUmdFuncs -}; +SceUID vshCallbackId = 0; +SceUID umdCallbackId; +SceUID umdCallbackThread; #define MAX_MODULE_NUMBER 256 -// Bogus read to test intercepting -static int patched_IoRead(PspIoDrvFileArg *arg, char *data, int len) + + +int lp_discChangeCallback(int unk, int event, void *data) { - Kprintf("Reading UMD data, hum dee dum...\n"); - return reserveUmdFuncs.IoRead(arg, data, len); + if (event == PSP_UMD_NOT_PRESENT) + lp_pingDiscRemoved(); + if (vshCallbackId) + sceKernelNotifyCallback(vshCallbackId, event); + return 0; +} + + +int lp_discChangeWatcher(SceSize argc, void *argp) +{ + SceUID callbacks[50]; + int count; + SceKernelCallbackInfo cbinfo; + + sceKernelGetThreadmanIdList(SCE_KERNEL_TMID_Callback, callbacks, 50, &count); + + for (int i = 0; i < count; i++) { + sceKernelReferCallbackStatus(callbacks[i], &cbinfo); + if (!strcmp(cbinfo.name, "SceVshMediaDetectUMD")) { + Kprintf("Found VSH UMD callback: 0x%08x\n", vshCallbackId); + vshCallbackId = callbacks[i]; + break; + } + } + + umdCallbackId = sceKernelCreateCallback("lp_discChangeCallback", + lp_discChangeCallback, + NULL); + sceUmdRegisterUMDCallBack(umdCallbackId); + + sceKernelSleepThreadCB(); } int module_start(SceSize argc, void *argp) { - PspIoDrv *umdDriver = 0; int ret; Kprintf("------------------\nUMD Livepatch starting...\n"); @@ -61,7 +76,6 @@ int module_start(SceSize argc, void *argp) umdDriver = sctrlHENFindDriver("umd"); if (umdDriver) { - originalUmdDriver = *umdDriver; reserveUmdFuncs = *umdDriver->funcs; Kprintf("Found UMD driver at 0x%08x\n", umdDriver); } else { @@ -69,9 +83,13 @@ int module_start(SceSize argc, void *argp) return 1; } - patchedUmdFuncs = reserveUmdFuncs; + umdCallbackThread = sceKernelCreateThread("lp_discChangeWatcher", + lp_discChangeWatcher, + 0x10, 0x1000, 0, NULL); + sceKernelStartThread(umdCallbackThread, 0, NULL); umdDriver->funcs->IoRead = patched_IoRead; + umdDriver->funcs->IoOpen = patched_IoOpen; umdDriver->funcs->IoDevctl = patched_IoDevctl; return 0; @@ -80,11 +98,16 @@ int module_start(SceSize argc, void *argp) int module_stop(void) { Kprintf("Unloading UMD Livepatch."); - sceIoDelDrv("umd"); - sceIoAddDrv(&originalUmdDriver); - sceIoDelDrv("umdraw"); - Kprintf("Restored original UMD driver\n"); + *umdDriver->funcs = reserveUmdFuncs; + Kprintf("Restored original UMD driver functions.\n"); + + sceUmdUnRegisterUMDCallBack(umdCallbackId); + sceKernelDeleteCallback(umdCallbackId); + + if (vshCallbackId) + sceUmdRegisterUMDCallBack(vshCallbackId); + Kprintf("Disconnected drive state callback.\n"); return 0; } diff --git a/rpatch.c b/rpatch.c index bbe4485..1191d4f 100644 --- a/rpatch.c +++ b/rpatch.c @@ -1,6 +1,8 @@ #include "io_funcs.h" #include "rpatch.h" +lp_UMDiffCommand cmd_buffer[1024]; + lp_UMDiffFile lp_PatchSet_open(const char *path) { @@ -12,3 +14,9 @@ lp_PatchSet_covered(lp_UMDiffCommand *ps, u32 offset) { } + +int +lp_loadCmdsForIndex(long sector) +{ + +} diff --git a/rpatch.h b/rpatch.h index 864b971..164c0b6 100644 --- a/rpatch.h +++ b/rpatch.h @@ -3,4 +3,7 @@ #include "umdiff/umdiff.h" +int +lp_loadCmdsForIndex(long sector); + #endif //__RPATCH_H