Add hook that provides functions with kernel access to the plugin

This commit is contained in:
Maschell 2018-06-30 19:40:59 +02:00
parent c959e86226
commit 763c5c2006
7 changed files with 115 additions and 1 deletions

View File

@ -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) { 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_FS);
CallHook(WUPS_LOADER_HOOK_INIT_OVERLAY); CallHook(WUPS_LOADER_HOOK_INIT_OVERLAY);
CallHook(WUPS_LOADER_HOOK_INIT_PLUGIN); CallHook(WUPS_LOADER_HOOK_INIT_PLUGIN);

View File

@ -68,6 +68,8 @@ struct replacement_data_plugin_t {
int32_t number_used_hooks; // Number of used hooks. Maximum is MAXIMUM_HOOKS_PER_PLUGIN 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. 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 #define MAXIMUM_PLUGINS 32

View File

@ -458,6 +458,10 @@ void PluginLoader::copyPluginDataIntoGlobalStruct(std::vector<PluginData *> plug
replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index]; 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->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); strncpy(plugin_data->path,cur_pluginInformation->getPath().c_str(),MAXIMUM_PLUGIN_PATH_NAME_LENGTH-1);

View File

@ -14,17 +14,30 @@
#include "common/common.h" #include "common/common.h"
#include "common/retain_vars.h" #include "common/retain_vars.h"
#include "myutils/overlay_helper.h" #include "myutils/overlay_helper.h"
#include "kernel/syscalls.h"
void CallHook(wups_loader_hook_type_t hook_type) { void CallHook(wups_loader_hook_type_t hook_type) {
CallHookEx(hook_type,-1); 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) { void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) {
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) { for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index]; replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index];
if(plugin_index_needed != -1 && plugin_index_needed != plugin_index) { if(plugin_index_needed != -1 && plugin_index_needed != plugin_index) {
continue; continue;
} }
#warning TODO: change the order of the wups_loader_hook_type_t enum before an offical release.
//DEBUG_FUNCTION_LINE("Checking hook functions for %s.\n",plugin_data->plugin_name); //DEBUG_FUNCTION_LINE("Checking hook functions for %s.\n",plugin_data->plugin_name);
//DEBUG_FUNCTION_LINE("Found hooks: %d\n",plugin_data->number_used_hooks); //DEBUG_FUNCTION_LINE("Found hooks: %d\n",plugin_data->number_used_hooks);
for(int32_t j=0; j<plugin_data->number_used_hooks; j++) { for(int32_t j=0; j<plugin_data->number_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) { if(gSDInitDone & WUPS_USB_MOUNTED) {
args.usb_mounted = true; 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); ((void (*)(wups_loader_app_started_args_t))((uint32_t*)func_ptr) )(args);
} else if(hook_type == WUPS_LOADER_HOOK_FUNCTIONS_PATCHED) { } else if(hook_type == WUPS_LOADER_HOOK_FUNCTIONS_PATCHED) {
((void (*)(void))((uint32_t*)func_ptr))(); ((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; status = WUPS_APP_STATUS_UNKNOWN;
} }
((void (*)(wups_loader_app_status_t))((uint32_t*)func_ptr))(status); ((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 { } else {
DEBUG_FUNCTION_LINE("ERROR: HOOK TYPE WAS NOT IMPLEMENTED %08X \n",hook_type); DEBUG_FUNCTION_LINE("ERROR: HOOK TYPE WAS NOT IMPLEMENTED %08X \n",hook_type);
} }

37
src/kernel.cpp Normal file
View File

@ -0,0 +1,37 @@
#include <wups.h>
#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

View File

@ -44,6 +44,7 @@ typedef enum wups_loader_hook_type_t {
WUPS_LOADER_HOOK_VSYNC, /* Called when an application calls GX2WaitForVsync (most times each frame) */ 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_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; } wups_loader_hook_type_t;
typedef struct wups_loader_hook_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 { typedef struct wups_loader_app_started_args_t {
bool sd_mounted; bool sd_mounted;
bool usb_mounted; bool usb_mounted;
bool kernel_access;
} wups_loader_app_started_args_t; } wups_loader_app_started_args_t;
#define WUPS_FS_ACCESS() \ #define WUPS_FS_ACCESS() \
@ -77,6 +79,13 @@ typedef struct wups_loader_app_started_args_t {
WUPS_InitOverlay(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() \ #define INITIALIZE_PLUGIN() \
void init_plugin(void);\ void init_plugin(void);\
WUPS_HOOK_EX(WUPS_LOADER_HOOK_INIT_PLUGIN,init_plugin); \ WUPS_HOOK_EX(WUPS_LOADER_HOOK_INIT_PLUGIN,init_plugin); \

View File

@ -67,7 +67,15 @@ typedef struct wups_loader_init_fs_args_t {
MKDirFunction mkdir_repl; MKDirFunction mkdir_repl;
} wups_loader_init_fs_args_t; } 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 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_InitFS(wups_loader_init_fs_args_t args);
void WUPS_InitOverlay(wups_loader_init_overlay_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. 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); 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 #ifdef __cplusplus
} }
#endif #endif