Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
yifanlu committed Jun 17, 2017
0 parents commit 9cf42cc
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 0 deletions.
43 changes: 43 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
cmake_minimum_required(VERSION 2.8)

if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()

project(usbmc)
include("${VITASDK}/share/vita.cmake" REQUIRED)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")

add_executable(usbmc
main.c
)

target_link_libraries(usbmc
SceIofilemgrForDriver_stub
SceSysclibForDriver_stub
SceSysmemForDriver_stub
SceModulemgrForKernel_stub
SceModulemgrForDriver_stub
SceThreadmgrForDriver_stub
taihenForKernel_stub
taihenModuleUtils_stub
)

vita_create_self(usbmc.skprx usbmc CONFIG exports.yml UNSAFE)

vita_create_stubs(stubs usbmc ${CMAKE_SOURCE_DIR}/exports.yml KERNEL)

install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/
DESTINATION lib
FILES_MATCHING PATTERN "*.a"
)

install(FILES vitashell_kernel.h
DESTINATION include
)
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
usbmc
=====
This is VitaShell's patches for USB storage support as a standalone plugin. If
loaded on startup (before SceShell), it will automatically mount the USB
storage as `ux0` instead of the memory card or internal memory.

To install, copy the plugin to `ur0:tai/usbmc.skprx` and add that path to the
taiHEN `ur0:tai/config.txt` under `*KERNEL`. If you have a memory card inserted
or you have a Vita with internal memory (LCD and PSTV), you must delete
`ux0:tai/config.txt` from the original memory and use `ur0:tai/config.txt` from
now on. This is because taiHEN loads before the memory card redirection patches
and will attempt to read config.txt from there first.

Full credits to The_FloW for these patches.
15 changes: 15 additions & 0 deletions exports.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
VitaShellKernel:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop
modules:
VitaShellKernelLibrary:
syscall: true
functions:
- shellKernelIsUx0Redirected
- shellKernelRedirectUx0
- shellKernelUnredirectUx0
206 changes: 206 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/*
VitaShell
Copyright (C) 2015-2017, TheFloW
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, either version 3 of the License, or
(at your option) any later version.
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 <http://www.gnu.org/licenses/>.
*/

#include <psp2kern/kernel/cpu.h>
#include <psp2kern/kernel/modulemgr.h>
#include <psp2kern/kernel/sysmem.h>
#include <psp2kern/io/fcntl.h>

#include <stdio.h>
#include <string.h>

#include <taihen.h>

#define MOUNT_POINT_ID 0x800

int module_get_offset(SceUID pid, SceUID modid, int segidx, size_t offset, uintptr_t *addr);

typedef struct {
const char *dev;
const char *dev2;
const char *blkdev;
const char *blkdev2;
int id;
} SceIoDevice;

typedef struct {
int id;
const char *dev_unix;
int unk;
int dev_major;
int dev_minor;
const char *dev_filesystem;
int unk2;
SceIoDevice *dev;
int unk3;
SceIoDevice *dev2;
int unk4;
int unk5;
int unk6;
int unk7;
} SceIoMountPoint;

static SceIoDevice uma_ux0_dev = { "ux0:", "exfatux0", "sdstor0:uma-pp-act-a", "sdstor0:uma-lp-act-entire", MOUNT_POINT_ID };

static SceIoMountPoint *(* sceIoFindMountPoint)(int id) = NULL;

static SceIoDevice *ori_dev = NULL, *ori_dev2 = NULL;

static SceUID hookid = -1;

static tai_hook_ref_t ksceSysrootIsSafeModeRef;

static tai_hook_ref_t ksceSblAimgrIsDolceRef;

static int ksceSysrootIsSafeModePatched() {
return 1;
}

static int ksceSblAimgrIsDolcePatched() {
return 1;
}

static int exists(const char *path) {
int fd = ksceIoOpen(path, SCE_O_RDONLY, 0);
if (fd < 0)
return 0;
ksceIoClose(fd);
return 1;
}

int shellKernelIsUx0Redirected() {
uint32_t state;
ENTER_SYSCALL(state);

SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID);
if (!mount) {
EXIT_SYSCALL(state);
return -1;
}

if (mount->dev == &uma_ux0_dev && mount->dev2 == &uma_ux0_dev) {
EXIT_SYSCALL(state);
return 1;
}

EXIT_SYSCALL(state);
return 0;
}

int shellKernelRedirectUx0() {
uint32_t state;
ENTER_SYSCALL(state);

SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID);
if (!mount) {
EXIT_SYSCALL(state);
return -1;
}

if (mount->dev != &uma_ux0_dev && mount->dev2 != &uma_ux0_dev) {
ori_dev = mount->dev;
ori_dev2 = mount->dev2;
}

mount->dev = &uma_ux0_dev;
mount->dev2 = &uma_ux0_dev;

EXIT_SYSCALL(state);
return 0;
}

int shellKernelUnredirectUx0() {
uint32_t state;
ENTER_SYSCALL(state);

SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID);
if (!mount) {
EXIT_SYSCALL(state);
return -1;
}

if (ori_dev && ori_dev2) {
mount->dev = ori_dev;
mount->dev2 = ori_dev2;

ori_dev = NULL;
ori_dev2 = NULL;
}

EXIT_SYSCALL(state);
return 0;
}

void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
SceUID tmp1, tmp2;
// Get tai module info
tai_module_info_t info;
info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceIofilemgr", &info) < 0)
return SCE_KERNEL_START_SUCCESS;

// Get important function
module_get_offset(KERNEL_PID, info.modid, 0, 0x138C1, (uintptr_t *)&sceIoFindMountPoint);

// Fake safe mode so that SceUsbMass can be loaded
tmp1 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceSysmem", 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched);
if (tmp1 < 0)
return SCE_KERNEL_START_SUCCESS;
// this patch is only needed on handheld units
tmp2 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSblAimgrIsDolceRef, "SceSysmem", 0xFD00C69A, 0x71608CA3, ksceSblAimgrIsDolcePatched);
if (tmp2 < 0)
return SCE_KERNEL_START_SUCCESS;

// Load SceUsbMass

// First try loading from bootimage
SceUID modid;
if (ksceKernelMountBootfs("os0:kd/bootimage.skprx") >= 0) {
modid = ksceKernelLoadStartModule("os0:kd/umass.skprx", 0, NULL, 0, NULL, NULL);
ksceKernelUmountBootfs();
} else {
// try loading from VitaShell
modid = ksceKernelLoadStartModule("ux0:VitaShell/module/umass.skprx", 0, NULL, 0, NULL, NULL);
}

// Release patch
taiHookReleaseForKernel(tmp1, ksceSysrootIsSafeModeRef);
taiHookReleaseForKernel(tmp2, ksceSblAimgrIsDolceRef);

// Check result
if (modid < 0)
return SCE_KERNEL_START_SUCCESS;

// Fake safe mode in SceUsbServ
hookid = taiHookFunctionImportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceUsbServ", 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched);

// start memory card redirection if we don't disable it
if (!exists("ur0:DISABLE_USB_MC.txt") && !shellKernelIsUx0Redirected()) {
shellKernelRedirectUx0();
}

return SCE_KERNEL_START_SUCCESS;
}

int module_stop(SceSize args, void *argp) {
if (hookid >= 0)
taiHookReleaseForKernel(hookid, ksceSysrootIsSafeModeRef);

return SCE_KERNEL_STOP_SUCCESS;
}
26 changes: 26 additions & 0 deletions vitashell_kernel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
VitaShell
Copyright (C) 2015-2017, TheFloW
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, either version 3 of the License, or
(at your option) any later version.
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 <http://www.gnu.org/licenses/>.
*/

#ifndef __VITASHELL_KERNEL_H__
#define __VITASHELL_KERNEL_H__

int shellKernelIsUx0Redirected();
int shellKernelRedirectUx0();
int shellKernelUnredirectUx0();

#endif

0 comments on commit 9cf42cc

Please sign in to comment.