From 92dab9c40010ed7c32435ff98c8114ec55a29e28 Mon Sep 17 00:00:00 2001 From: Li Date: Tue, 6 Feb 2024 14:49:27 +1300 Subject: [PATCH] Add OTG support --- app/sfo.c | 65 ++++++++++++++++++++------------ kern/CMakeLists.txt | 1 + kern/main.c | 4 +- kern/otg.c | 92 +++++++++++++++++++++++++++++++++++++++++++++ kern/otg.h | 2 + 5 files changed, 138 insertions(+), 26 deletions(-) create mode 100644 kern/otg.c create mode 100644 kern/otg.h diff --git a/app/sfo.c b/app/sfo.c index ca7ce47..254a932 100644 --- a/app/sfo.c +++ b/app/sfo.c @@ -1,67 +1,82 @@ -#include "sfo.h" #include #include #include - -static uint8_t SFO_BUFFER[0x10000]; - +#include +#include "sfo.h" +#include "io.h" +#include "err.h" int read_sfo_key(char* key, char* out, char* sfo) { - memset(SFO_BUFFER, 0x00, sizeof(SFO_BUFFER)); + int ret = 0; + + uint64_t sfo_size = get_file_size(sfo); + if(sfo_size <= 0) ERROR(sfo_size); + + char* sfo_buffer = malloc(sfo_size); + if(sfo_buffer == NULL) ERROR(-1); + + memset(sfo_buffer, 0x00, sfo_size); + // open sfo file int sfo_fd = sceIoOpen(sfo, SCE_O_RDONLY, 0777); - if(sfo_fd < 0) return sfo_fd; - + if(sfo_fd < 0) ERROR(sfo_fd); // read sfo - int sfo_size = sceIoRead(sfo_fd, SFO_BUFFER, sizeof(SFO_BUFFER)); + + int rd = sceIoRead(sfo_fd, sfo_buffer, sfo_size); + if(rd != sfo_size) ERROR(-2); + // close sfo - sceIoClose(sfo_fd); - - if(sfo_size < 0) return sfo_size; - if(sfo_size >= sizeof(SFO_BUFFER)) return -1; - if(sfo_size <= sizeof(sfo_header)) return -2; + if(sceIoClose(sfo_fd) >= 0) + sfo_fd = 0; + + if(sfo_size <= sizeof(sfo_header)) ERROR(-3); // get sfo header sfo_header header; - memcpy(&header, SFO_BUFFER, sizeof(sfo_header)); + memcpy(&header, sfo_buffer, sizeof(sfo_header)); - if(memcmp(header.magic, "\0PSF", sizeof(header.magic)) != 0) return -3; // check magic - if(header.count > 200) return -4; // give up if more than 200 keys - if(sfo_size < (sizeof(sfo_header) + (sizeof(sfo_key) * header.count))) return -5; // check if size is enough for keys + sfo header size + if(memcmp(header.magic, "\0PSF", sizeof(header.magic)) != 0) ERROR(-4); // check magic + if(header.count > 200) ERROR(-5); // give up if more than 200 keys + if(sfo_size < (sizeof(sfo_header) + (sizeof(sfo_key) * header.count))) ERROR(-6); // check if size is enough for keys + sfo header size uint32_t ptr = sizeof(sfo_header); // read keys for(int i = 0; i < header.count; i++) { - if(ptr >= sizeof(SFO_BUFFER)) return -6; // check for overflow + if(ptr > sfo_size) ERROR(-7); // check for overflow char key_name[64]; char key_value[64]; sfo_key s_key; - memcpy(&s_key, SFO_BUFFER+ptr, sizeof(sfo_key)); + memcpy(&s_key, sfo_buffer+ptr, sizeof(sfo_key)); ptr += sizeof(sfo_key); if(s_key.type != PSF_TYPE_STR) continue; // calculate location of key in buffer int name_offset = header.key_offset + s_key.name_offset; - if(name_offset > sfo_size) return -7; + if(name_offset > sfo_size) ERROR(-8); int data_offset = header.value_offset + s_key.data_offset; - if(data_offset > sfo_size) return -8; + if(data_offset > sfo_size) ERROR(-9); // copy the key and value into buffers. - strncpy(key_name, SFO_BUFFER + name_offset, sizeof(key_name)-1); - strncpy(key_value, SFO_BUFFER + data_offset, sizeof(key_value)-1); + strncpy(key_name, sfo_buffer + name_offset, sizeof(key_name)-1); + strncpy(key_value, sfo_buffer + data_offset, sizeof(key_value)-1); if(strncmp(key_name, key, sizeof(key_name)) == 0){ strncpy(out, key_value, sizeof(key_value)-1); - return 0; + ERROR(0); } } - return -9; +error: + if(sfo_buffer != NULL) + free(sfo_buffer); + if(sfo_fd > 0) + sceIoClose(sfo_fd); + return ret; } \ No newline at end of file diff --git a/kern/CMakeLists.txt b/kern/CMakeLists.txt index 6f8bb4d..3fba058 100644 --- a/kern/CMakeLists.txt +++ b/kern/CMakeLists.txt @@ -24,6 +24,7 @@ add_executable(${PROJECT_NAME} f00d.c io.c cobra.c + otg.c format.c cmd56.c ) diff --git a/kern/main.c b/kern/main.c index 304353b..f3c86a7 100644 --- a/kern/main.c +++ b/kern/main.c @@ -10,7 +10,8 @@ void _start() __attribute__((weak, alias("module_start"))); int module_start(SceSize argc, const void *args) { cobra_patch(); // revert cobra blackfin patch - cmd56_patch(); // patch cmd56 .. + otg_patch(); // enable otg + cmd56_patch(); // patch cmd56 get_module_functions(); // get format stuff return SCE_KERNEL_START_SUCCESS; @@ -20,5 +21,6 @@ int module_stop(SceSize argc, const void *args) { cobra_unpatch(); cmd56_unpatch(); + otg_unpatch(); return SCE_KERNEL_STOP_SUCCESS; } diff --git a/kern/otg.c b/kern/otg.c new file mode 100644 index 0000000..0ec0f48 --- /dev/null +++ b/kern/otg.c @@ -0,0 +1,92 @@ +#include "log.h" +#include +#include +#include + +SceUID sceSysconSetOtgPowerLevelHook = -1; +static tai_hook_ref_t sceSysconSetOtgPowerLevelHookRef; + + +static int return_1() { + return 1; +} + +// shamelessly stolen from dots_tb +static SceUID sceSysconSetOtgPowerLevel_patched(uint32_t *pwr_val) { + SceUID ret, state; + ENTER_SYSCALL(state); + + ret = TAI_CONTINUE(SceUID, sceSysconSetOtgPowerLevelHookRef, pwr_val); + PRINT_STR("sceSysconSetOtgPowerLevel original %x\n", *pwr_val); + if(*pwr_val == 0x700) + PRINT_STR("sceSysconSetOtgPowerLevel new %x\n\n", *pwr_val = 0x200); + + EXIT_SYSCALL(state); + return ret; + +} + +// force load usb mass storage plugin on all devices +int load_umass() { + if(ksceKernelSearchModuleByName("SceUsbMass") < 0) { + tai_hook_ref_t ksceSysrootIsSafeModeHookRef; + tai_hook_ref_t ksceSblAimgrIsDolceHookRef; + + // temporarily patch isSafeMode and isDolce + SceUID ksceSysrootIsSafeModeHook = taiHookFunctionExportForKernel(KERNEL_PID, + &ksceSysrootIsSafeModeHookRef, + "SceSysmem", + 0x2ED7F97A, // SceSysrootForKernel + 0x834439A7, // ksceSysrootIsSafemode + return_1); + + PRINT_STR("ksceSysrootIsSafeModeHook 0x%04X\n", ksceSysrootIsSafeModeHook); + PRINT_STR("ksceSysrootIsSafeModeHookRef 0x%04X\n", ksceSysrootIsSafeModeHookRef); + + + SceUID ksceSblAimgrIsDolceHook = taiHookFunctionExportForKernel(KERNEL_PID, + &ksceSblAimgrIsDolceHookRef, + "SceSysmem", + 0xFD00C69A, // SceSblAIMgrForDriver + 0x71608CA3, // ksceSblAimgrIsDolce + return_1); + + PRINT_STR("ksceSblAimgrIsDolceHook 0x%04X\n", ksceSblAimgrIsDolceHook); + PRINT_STR("ksceSblAimgrIsDolceHookRef 0x%04X\n", ksceSblAimgrIsDolceHookRef); + + // start from here, technically the module is actually in os0 bootimage + // but cannot start after system already started, unfortunately. + SceUID umass_modid = ksceKernelLoadStartModule("ux0:VitaShell/module/umass.skprx", 0, NULL, 0, NULL, NULL); + PRINT_STR("Load umass.skprx 0x%04X\n", umass_modid); + + // release hooks + if(ksceSysrootIsSafeModeHook > 0) taiHookReleaseForKernel(ksceSysrootIsSafeModeHook, ksceSysrootIsSafeModeHookRef); + if(ksceSblAimgrIsDolceHook > 0) taiHookReleaseForKernel(ksceSblAimgrIsDolceHook, ksceSblAimgrIsDolceHookRef); + if(umass_modid < 0) return umass_modid; + } + + return 0; +} + +int otg_patch() { + // improve compatibility with OTG connectors + sceSysconSetOtgPowerLevelHook = taiHookFunctionImportForKernel(KERNEL_PID, + &sceSysconSetOtgPowerLevelHookRef, + "SceUsbServ", + TAI_ANY_LIBRARY, + 0xD6F6D472, // sceSysconSetOtgPowerLevel + sceSysconSetOtgPowerLevel_patched); + + PRINT_STR("sceSysconSetOtgPowerLevelHook 0x%04X\n", sceSysconSetOtgPowerLevelHook); + PRINT_STR("sceSysconSetOtgPowerLevelHookRef 0x%04X\n", sceSysconSetOtgPowerLevelHookRef); + + // allow loading usb storage on regular vita + load_umass(); + + return 0; +} + +int otg_unpatch() { + if(sceSysconSetOtgPowerLevelHook >= 0) taiHookReleaseForKernel(sceSysconSetOtgPowerLevelHook, sceSysconSetOtgPowerLevelHookRef); + return 0; +} \ No newline at end of file diff --git a/kern/otg.h b/kern/otg.h new file mode 100644 index 0000000..5c9c0ea --- /dev/null +++ b/kern/otg.h @@ -0,0 +1,2 @@ +int otg_patch(); +int otg_unpatch(); \ No newline at end of file