Add OTG support

This commit is contained in:
Li 2024-02-06 14:49:27 +13:00
parent 558b381a4d
commit 92dab9c400
5 changed files with 138 additions and 26 deletions

View File

@ -1,67 +1,82 @@
#include "sfo.h"
#include <vitasdk.h>
#include <string.h>
#include <stdio.h>
static uint8_t SFO_BUFFER[0x10000];
#include <stdlib.h>
#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;
}

View File

@ -24,6 +24,7 @@ add_executable(${PROJECT_NAME}
f00d.c
io.c
cobra.c
otg.c
format.c
cmd56.c
)

View File

@ -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;
}

92
kern/otg.c Normal file
View File

@ -0,0 +1,92 @@
#include "log.h"
#include <vitasdkkern.h>
#include <taihen.h>
#include <stdint.h>
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;
}

2
kern/otg.h Normal file
View File

@ -0,0 +1,2 @@
int otg_patch();
int otg_unpatch();