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