diff --git a/.gitignore b/.gitignore index 33fc017..9092ab4 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,6 @@ dkms.conf app/drivers/audio_driver.S app/drivers/display_driver.S app/drivers/fs_driver.S -app/drivers/input_driver.S +app/drivers/module_driver.S app/*.json app/*.log diff --git a/Makefile b/Makefile index 8f959f5..27ee0f8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = audio_driver display_driver fs_driver app launcher +SUBDIRS = audio_driver display_driver fs_driver module_driver app launcher all: @for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done diff --git a/app/include/kernel_functions.h b/app/include/kernel_functions.h index dd8946d..69278b1 100644 --- a/app/include/kernel_functions.h +++ b/app/include/kernel_functions.h @@ -7,6 +7,7 @@ extern "C" { #include #include +#include // Kernel function prototypes @@ -34,6 +35,9 @@ extern int pspIoRename(const char *oldname, const char *newname); extern int pspIoRemoveFile(const char *file); extern int pspIoDevctl(const char *dev, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen); +// module_driver functions +extern int pspKernelLoadModuleBuffer(SceSize size, void *buf, s32 flag, const SceKernelLMOption *option); + #if defined (__cplusplus) } #endif diff --git a/app/source/kernel_functions.cpp b/app/source/kernel_functions.cpp index d5aa225..aa8e4c0 100644 --- a/app/source/kernel_functions.cpp +++ b/app/source/kernel_functions.cpp @@ -23,3 +23,6 @@ int pspIoGetstat(const char *file, SceIoStat *stat); int pspIoRename(const char *oldname, const char *newname); int pspIoRemoveFile(const char *file); int pspIoDevctl(const char *dev, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen); + +// module_driver functions +int pspKernelLoadModuleBuffer(SceSize size, void *buf, s32 flag, const SceKernelLMOption *option); diff --git a/app/source/utils.cpp b/app/source/utils.cpp index 9e72f8c..22b52d3 100644 --- a/app/source/utils.cpp +++ b/app/source/utils.cpp @@ -21,8 +21,8 @@ enum PspCtrlButtons PSP_CTRL_ENTER, PSP_CTRL_CANCEL; BROWSE_STATE device = BROWSE_STATE_EXTERNAL; int g_psp_language = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; -extern unsigned char audio_driver_prx_start[], display_driver_prx_start[], fs_driver_prx_start[]; -extern unsigned int audio_driver_prx_size, display_driver_prx_size, fs_driver_prx_size; +extern unsigned char audio_driver_prx_start[], display_driver_prx_start[], fs_driver_prx_start[], module_driver_prx_start[]; +extern unsigned int audio_driver_prx_size, display_driver_prx_size, fs_driver_prx_size, module_driver_prx_size; namespace Utils { constexpr unsigned int CTRL_DEADZONE_DELAY = 500000; @@ -33,6 +33,7 @@ namespace Utils { static int last_button_tick = 0, deadzone_tick = 0; static bool usb_module_loaded = false; static bool usb_actived = false; + static SceUID module_driver_id = 0; typedef struct { const char *path = nullptr; @@ -116,7 +117,7 @@ namespace Utils { } // Basically removes and re-creates prx from memory -> then remove it after inital load - static int LoadStartModuleMem(const char *path, const void *buf, SceSize size) { + static int LoadStartModuleMemInitial(const char *path, const void *buf, SceSize size) { int ret = 0; SceUID modID = 0; @@ -140,6 +141,23 @@ namespace Utils { return 0; } + static int LoadStartModuleMem(const char *path, void *buf, SceSize size) { + int ret = 0; + SceUID modID = 0; + + if (R_FAILED(ret = modID = pspKernelLoadModuleBuffer(size, buf, 0, nullptr))) { + Log::Error("kuKernelLoadModule(%s) failed: 0x%08x\n", path, ret); + return ret; + } + + if (R_FAILED(ret = sceKernelStartModule(modID, 0, nullptr, nullptr, nullptr))) { + Log::Error("sceKernelStartModule(%s) failed: 0x%08x\n", path, ret); + return ret; + } + + return 0; + } + static void StopUnloadModules(SceUID modID) { sceKernelStopModule(modID, 0, nullptr, nullptr, nullptr); sceKernelUnloadModule(modID); @@ -245,6 +263,8 @@ namespace Utils { } void InitKernelDrivers(void) { + module_driver_id = LoadStartModuleMemInitial("module_driver.prx", module_driver_prx_start, module_driver_prx_size); + for (unsigned int i = 0; i < kernel_modules.size(); ++i) kernel_modules[i].id = Utils::LoadStartModuleMem(kernel_modules[i].path, kernel_modules[i].data, kernel_modules[i].size); @@ -252,12 +272,14 @@ namespace Utils { } void TermKernelDrivers(void) { + Utils::ExitUSB(); + for (int i = kernel_modules.size() - 1; i >= 0; --i) { Utils::StopUnloadModules(kernel_modules[i].id); kernel_modules[i].id = -1; } - Utils::ExitUSB(); + Utils::StopUnloadModules(module_driver_id); } void UpdateUSB(void) { diff --git a/module_driver/Makefile b/module_driver/Makefile new file mode 100644 index 0000000..3cde7fc --- /dev/null +++ b/module_driver/Makefile @@ -0,0 +1,23 @@ +TARGET = module_driver +OBJS = module_driver.o exports.o ModuleMgrForKernel.o + +PRX_EXPORTS = exports.exp + +# Use the kernel's small inbuilt libc +USE_KERNEL_LIBC = 1 +# Use only kernel libraries +USE_KERNEL_LIBS = 1 + +CFLAGS = -Os -G0 -Wall -fno-builtin-printf +CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti +ASFLAGS = $(CFLAGS) + +LDFLAGS = -nostartfiles + +PSPSDK=$(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build_prx.mak + +all: + psp-build-exports -s $(PRX_EXPORTS) + mv module_driver.S "../app/drivers/" + mv module_driver.prx "../app/data/" diff --git a/module_driver/ModuleMgrForKernel.S b/module_driver/ModuleMgrForKernel.S new file mode 100644 index 0000000..2516661 --- /dev/null +++ b/module_driver/ModuleMgrForKernel.S @@ -0,0 +1,18 @@ + .set noreorder + +#include "pspimport.s" + + IMPORT_START "ModuleMgrForKernel",0x00010000 + IMPORT_FUNC "ModuleMgrForKernel",0xFFB9B760,sceKernelLoadModule + IMPORT_FUNC "ModuleMgrForKernel",0xE6BF3960,sceKernelStartModule + IMPORT_FUNC "ModuleMgrForKernel",0x0D053026,sceKernelUnloadModule + IMPORT_FUNC "ModuleMgrForKernel",0x32292450,_sceKernelLoadModuleWithApitype2 + IMPORT_FUNC "ModuleMgrForKernel",0xE3CCC6EA,sceKernelLoadModule_620 + IMPORT_FUNC "ModuleMgrForKernel",0xDF8FFFAB,sceKernelStartModule_620 + IMPORT_FUNC "ModuleMgrForKernel",0x9CEB18C4,sceKernelUnloadModule_620 + IMPORT_FUNC "ModuleMgrForKernel",0xB691CB9F,sceKernelLoadModuleWithApitype2_620 + IMPORT_FUNC "ModuleMgrForKernel",0x939E4270,sceKernelLoadModule_660 + IMPORT_FUNC "ModuleMgrForKernel",0x3FF74DF1,sceKernelStartModule_660 + IMPORT_FUNC "ModuleMgrForKernel",0x387E3CA9,sceKernelUnloadModule_660 + IMPORT_FUNC "ModuleMgrForKernel",0x2B7FC10D,sceKernelLoadModuleWithApitype2_660 + IMPORT_FUNC "ModuleMgrForKernel",0x4E62C48A,sceKernelLoadModuleBufferForKernel diff --git a/module_driver/exports.exp b/module_driver/exports.exp new file mode 100644 index 0000000..04d805a --- /dev/null +++ b/module_driver/exports.exp @@ -0,0 +1,16 @@ +# Define the exports for the prx +PSP_BEGIN_EXPORTS + +# These four lines are mandatory (although you can add other functions like module_stop) +# syslib is a psynonym for the single mandatory export. +PSP_EXPORT_START(syslib, 0, 0x8000) +PSP_EXPORT_FUNC(module_start) +PSP_EXPORT_FUNC(module_stop) +PSP_EXPORT_VAR(module_info) +PSP_EXPORT_END + +PSP_EXPORT_START(module_driver, 0, 0x4001) +PSP_EXPORT_FUNC(pspKernelLoadModuleBuffer) +PSP_EXPORT_END + +PSP_END_EXPORTS diff --git a/module_driver/module_driver.c b/module_driver/module_driver.c new file mode 100644 index 0000000..7bda7c6 --- /dev/null +++ b/module_driver/module_driver.c @@ -0,0 +1,21 @@ +#include + +PSP_MODULE_INFO("module_driver", PSP_MODULE_KERNEL, 1, 0); +PSP_NO_CREATE_MAIN_THREAD(); + +SceUID sceKernelLoadModuleBufferForKernel(SceSize size, void *buf, s32 flag, const SceKernelLMOption *option); + +int pspKernelLoadModuleBuffer(SceSize size, void *buf, s32 flag, const SceKernelLMOption *option) { + int k1 = pspSdkSetK1(0); + int ret = sceKernelLoadModuleBufferForKernel(size, buf, flag, option); + pspSdkSetK1(k1); + return ret; +} + +int module_start(SceSize args, void *argp) { + return 0; +} + +int module_stop(void) { + return 0; +}