diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 6502fb1..d291c47 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -173,6 +173,7 @@ extern "C" int32_t Menu_Main(int32_t argc, char **argv) { if(result == APPLICATION_CLOSE_APPLY || result == APPLICATION_CLOSE_APPLY_MEMORY) { + CallHook(WUPS_LOADER_HOOK_INIT_KERNEL); CallHook(WUPS_LOADER_HOOK_INIT_FS); CallHook(WUPS_LOADER_HOOK_INIT_OVERLAY); CallHook(WUPS_LOADER_HOOK_INIT_PLUGIN); diff --git a/loader/src/patcher/function_patcher.h b/loader/src/patcher/function_patcher.h index 211cbe9..755495a 100644 --- a/loader/src/patcher/function_patcher.h +++ b/loader/src/patcher/function_patcher.h @@ -68,6 +68,8 @@ struct replacement_data_plugin_t { int32_t number_used_hooks; // Number of used hooks. Maximum is MAXIMUM_HOOKS_PER_PLUGIN replacement_data_hook_t hooks[MAXIMUM_HOOKS_PER_PLUGIN]; // Replacement information for each function. + bool kernel_allowed; // Allow kernel access for the plugin!?!. + bool kernel_init_done; // KernelInit was done }; #define MAXIMUM_PLUGINS 32 diff --git a/loader/src/plugin/PluginLoader.cpp b/loader/src/plugin/PluginLoader.cpp index e4c410e..601bf98 100644 --- a/loader/src/plugin/PluginLoader.cpp +++ b/loader/src/plugin/PluginLoader.cpp @@ -458,6 +458,10 @@ void PluginLoader::copyPluginDataIntoGlobalStruct(std::vector plug replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index]; + #warning TODO: add GUI option to let the user choose + plugin_data->kernel_allowed = true; + plugin_data->kernel_init_done = false; + strncpy(plugin_data->plugin_name,cur_pluginInformation->getName().c_str(),MAXIMUM_PLUGIN_NAME_LENGTH-1); strncpy(plugin_data->path,cur_pluginInformation->getPath().c_str(),MAXIMUM_PLUGIN_PATH_NAME_LENGTH-1); diff --git a/loader/src/utils.cpp b/loader/src/utils.cpp index d866e03..cc44b7e 100644 --- a/loader/src/utils.cpp +++ b/loader/src/utils.cpp @@ -14,17 +14,30 @@ #include "common/common.h" #include "common/retain_vars.h" #include "myutils/overlay_helper.h" +#include "kernel/syscalls.h" void CallHook(wups_loader_hook_type_t hook_type) { CallHookEx(hook_type,-1); } +#ifdef __cplusplus +extern "C" { +#endif + // Part of libutils + extern uint32_t kern_read(const void *addr); + extern void kern_write(void *addr, uint32_t value); +#ifdef __cplusplus +} +#endif + void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) { for(int32_t plugin_index=0; plugin_indexplugin_name); //DEBUG_FUNCTION_LINE("Found hooks: %d\n",plugin_data->number_used_hooks); for(int32_t j=0; jnumber_used_hooks; j++) { @@ -67,6 +80,9 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) if(gSDInitDone & WUPS_USB_MOUNTED) { args.usb_mounted = true; } + if(plugin_data->kernel_allowed && plugin_data->kernel_init_done){ + args.kernel_access = true; + } ((void (*)(wups_loader_app_started_args_t))((uint32_t*)func_ptr) )(args); } else if(hook_type == WUPS_LOADER_HOOK_FUNCTIONS_PATCHED) { ((void (*)(void))((uint32_t*)func_ptr))(); @@ -86,6 +102,16 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) status = WUPS_APP_STATUS_UNKNOWN; } ((void (*)(wups_loader_app_status_t))((uint32_t*)func_ptr))(status); + } else if(hook_type == WUPS_LOADER_HOOK_INIT_KERNEL){ + // Only call the hook if kernel is allowed. + if(plugin_data->kernel_allowed){ + wups_loader_init_kernel_args_t args; + args.kern_read_ptr = &kern_read; + args.kern_write_ptr = &kern_write; + args.kern_copy_data_ptr = &SC0x25_KernelCopyData; + ((void (*)(wups_loader_init_kernel_args_t))((uint32_t*)func_ptr) )(args); + plugin_data->kernel_init_done = true; + } } else { DEBUG_FUNCTION_LINE("ERROR: HOOK TYPE WAS NOT IMPLEMENTED %08X \n",hook_type); } diff --git a/src/kernel.cpp b/src/kernel.cpp new file mode 100644 index 0000000..2cb684e --- /dev/null +++ b/src/kernel.cpp @@ -0,0 +1,37 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static KernelReadFunction kern_read_ptr __attribute__((section(".data"))) = NULL; +static KernelWriteFunction kern_write_ptr __attribute__((section(".data"))) = NULL; +static KernelCopyDataFunction kern_copy_data_ptr __attribute__((section(".data"))) = NULL; + +void WUPS_InitKernel(wups_loader_init_kernel_args_t args) { + kern_read_ptr = args.kern_read_ptr; + kern_write_ptr = args.kern_write_ptr; + kern_copy_data_ptr = args.kern_copy_data_ptr; +} + +uint32_t WUPS_KernelRead(const void *addr) { + if(kern_read_ptr != NULL) { + return kern_read_ptr(addr); + } + return 0; +} + +void WUPS_KernelWrite(void *addr, uint32_t value) { + if(kern_write_ptr != NULL) { + kern_write_ptr(addr, value); + } +} +void WUPS_KernelCopyDataFunction(uint32_t addr, uint32_t src, uint32_t len) { + if(kern_copy_data_ptr != NULL) { + kern_copy_data_ptr(addr, src, len); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/wups_include/wups/hooks.h b/wups_include/wups/hooks.h index 72d8df2..6c0c0c7 100644 --- a/wups_include/wups/hooks.h +++ b/wups_include/wups/hooks.h @@ -43,7 +43,8 @@ typedef enum wups_loader_hook_type_t { WUPS_LOADER_HOOK_ENDING_APPLICATION, /* Called when an application ends */ WUPS_LOADER_HOOK_VSYNC, /* Called when an application calls GX2WaitForVsync (most times each frame) */ WUPS_LOADER_HOOK_APP_STATUS_CHANGED, /* Called when the app status changes (foreground, background, closing) */ - + + WUPS_LOADER_HOOK_INIT_KERNEL, /* Only for internal usage */ } wups_loader_hook_type_t; typedef struct wups_loader_hook_t { @@ -61,6 +62,7 @@ typedef enum wups_loader_app_status_t { typedef struct wups_loader_app_started_args_t { bool sd_mounted; bool usb_mounted; + bool kernel_access; } wups_loader_app_started_args_t; #define WUPS_FS_ACCESS() \ @@ -76,6 +78,13 @@ typedef struct wups_loader_app_started_args_t { void init_overlay(wups_loader_init_overlay_args_t args){ \ WUPS_InitOverlay(args);\ } + +#define WUPS_ALLOW_KERNEL() \ + void init_kernel(wups_loader_init_kernel_args_t);\ + WUPS_HOOK_EX(WUPS_LOADER_HOOK_INIT_KERNEL,init_kernel); \ + void init_kernel(wups_loader_init_kernel_args_t args){ \ + WUPS_InitKernel(args);\ + } #define INITIALIZE_PLUGIN() \ void init_plugin(void);\ diff --git a/wups_include/wups/utils.h b/wups_include/wups/utils.h index f5a28ea..2cd90df 100644 --- a/wups_include/wups/utils.h +++ b/wups_include/wups/utils.h @@ -67,7 +67,15 @@ typedef struct wups_loader_init_fs_args_t { MKDirFunction mkdir_repl; } wups_loader_init_fs_args_t; +typedef uint32_t (*KernelReadFunction)(const void *addr); +typedef void (*KernelWriteFunction)(void *addr, uint32_t value); +typedef void (*KernelCopyDataFunction)(uint32_t addr, uint32_t src, uint32_t len); +typedef struct wups_loader_init_kernel_args_t_ { + KernelReadFunction kern_read_ptr; + KernelWriteFunction kern_write_ptr; + KernelCopyDataFunction kern_copy_data_ptr; +} wups_loader_init_kernel_args_t; /* Gets called by the framework @@ -75,6 +83,12 @@ typedef struct wups_loader_init_fs_args_t { void WUPS_InitFS(wups_loader_init_fs_args_t args); void WUPS_InitOverlay(wups_loader_init_overlay_args_t args); +/** + Sets the function pointers for kernel functions. + If none or NULL pointers is provided, calling the corresponding function has no effect. +**/ +void WUPS_InitKernel(wups_loader_init_kernel_args_t args); + /* Can be called by the user. */ @@ -86,6 +100,27 @@ void WUPS_Overlay_FlipBuffers(wups_overlay_options_type_t screen); void WUPS_OpenOverlay(wups_overlay_options_type_t screen, overlay_callback callback); +/** + Reads a 32bit value from a given address with kernel rights. + This function only has an effect if the plugin has the "WUPS_ALLOW_KERNEL" hook and the loader is NOT blocking the kernel access. + The argument of the ON_APPLICATION_START hook provides the information if the plugin has kernel access which should be checked before using/relying on this function. +**/ +uint32_t WUPS_KernelRead(const void *addr); + +/** + Write a 32bit value from a given address with kernel rights. + This function only has an effect if the plugin has the "WUPS_ALLOW_KERNEL" hook and the loader is NOT blocking the kernel access. + The argument of the ON_APPLICATION_START hook provides the information if the plugin has kernel access which should be checked before using/relying on this function. +**/ +void WUPS_KernelWrite(void *addr, uint32_t value); + +/** + Copies data from a source address to a destination address for a given lenght with kernel rights. + This function only has an effect if the plugin has the "WUPS_ALLOW_KERNEL" hook and the loader is NOT blocking the kernel access. + The argument of the ON_APPLICATION_START hook provides the information if the plugin has kernel access which should be checked before using/relying on this function. +**/ +void WUPS_KernelCopyDataFunction(uint32_t addr, uint32_t src, uint32_t len); + #ifdef __cplusplus } #endif