[Loader] Added support for the init hook.

- The loader now returns to the system menu and restores all patches when entering mii maker.
This commit is contained in:
Maschell 2018-02-10 17:05:11 +01:00
parent 81b5bed341
commit ec217c6aef
4 changed files with 162 additions and 15 deletions

View File

@ -40,8 +40,16 @@
#include <unistd.h>
#include <dynamic_libs/os_functions.h>
//TODO: Adjust this.
#define MODULE_ENTRIES_CAPACITY_DEFAULT 128
//TODO: Adjust this.
#define MODULE_HOOKS_CAPACITY_DEFAULT 128
wups_loader_hook_t *module_hooks = NULL;
size_t module_hooks_count = 0;
size_t module_hooks_capacity = 0;
wups_loader_entry_t *module_entries = NULL;
size_t module_entries_count = 0;
size_t module_entries_capacity = 0;
@ -106,10 +114,11 @@ exit_error:
bool Module_LinkModuleElf(size_t index, Elf *elf, uint8_t **space) {
Elf_Scn *scn;
size_t symtab_count, section_count, shstrndx, symtab_strndx, entries_count;
size_t symtab_count, section_count, shstrndx, symtab_strndx, entries_count, hooks_count;
Elf32_Sym *symtab = NULL;
uint8_t **destinations = NULL;
wups_loader_entry_t *entries = NULL;
wups_loader_hook_t *hooks = NULL;
bool result = false;
if (!Module_LoadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx))
@ -171,6 +180,30 @@ bool Module_LinkModuleElf(size_t index, Elf *elf, uint8_t **space) {
gbl_replacement_data.module_data[index].functions[i].entry_index = entries_offset +i;
gbl_replacement_data.module_data[index].number_used_functions++;
}
}else if (strcmp(name, ".wups.hooks") == 0) {
if (hooks != NULL)
goto exit_error;
hooks_count = shdr->sh_size / sizeof(wups_loader_hook_t);
hooks = (wups_loader_hook_t*) Module_ListAllocate(
&module_hooks, sizeof(wups_loader_hook_t),
hooks_count, &module_hooks_capacity,
&module_hooks_count, MODULE_HOOKS_CAPACITY_DEFAULT);
if (hooks == NULL)
goto exit_error;
destinations[elf_ndxscn(scn)] = (uint8_t *)hooks;
if (!Module_ElfLoadSection(elf, scn, shdr, hooks))
goto exit_error;
Module_ElfLoadSymbols(elf_ndxscn(scn), hooks, symtab, symtab_count);
int hook_offset = module_hooks_count - hooks_count;
for(int i = 0;i< hooks_count;i++){
gbl_replacement_data.module_data[index].hooks[i].hook_index = hook_offset +i;
gbl_replacement_data.module_data[index].number_used_hooks++;
}
} else {
*space -= shdr->sh_size;
@ -244,6 +277,20 @@ bool Module_ListLinkFinal() {
for(int module_index=0;module_index<gbl_replacement_data.number_used_modules;module_index++){
replacement_data_module_t * module_data = &gbl_replacement_data.module_data[module_index];
DEBUG_FUNCTION_LINE("Module name: %s\n",module_data->module_name);
for(int j=0;j<module_data->number_used_hooks;j++){
replacement_data_hook_t * hook_data = &module_data->hooks[j];
if(hook_data->hook_index > module_entries_count-1){
DEBUG_FUNCTION_LINE("Error. hook_index was too high: %d. maximum is %d\n",hook_data->hook_index,module_entries_count-1);
goto exit_error;
}
wups_loader_hook_t * hook = &module_hooks[hook_data->hook_index];
DEBUG_FUNCTION_LINE("Set hook %d of module \"%s\" of type %08X\n",hook_data->hook_index,module_data->module_name,hook->type);
hook_data->func_pointer = (void*) hook->target;
hook_data->type = hook->type;
}
DEBUG_FUNCTION_LINE("number of used function: %d\n",module_data->number_used_functions);
for(int j=0;j<module_data->number_used_functions;j++){
replacement_data_function_t * function_data = &module_data->functions[j];

View File

@ -7,7 +7,9 @@
#include <dynamic_libs/os_functions.h>
#include <dynamic_libs/socket_functions.h>
#include <dynamic_libs/sys_functions.h>
#include <dynamic_libs/fs_functions.h>
#include <dynamic_libs/vpad_functions.h>
#include <utils/logger.h>
#include <fs/FSUtils.h>
#include <fs/sd_fat_devoptab.h>
@ -27,13 +29,23 @@
#include "patcher/function_patcher.h"
static void printModuleInfos();
static void loadSamplePlugin();
static void printInfos();
static void printReplacementInfos();
static void ApplyPatches();
void CallHook(wups_loader_hook_type_t hook_type);
static void RestorePatches();
s32 isInMiiMakerHBL();
u8 isFirstBoot __attribute__((section(".data"))) = 1;
/* Entry point */
extern "C" int Menu_Main(int argc, char **argv){
InitOSFunctionPointers();
InitSocketFunctionPointers(); //For logging
InitSysFunctionPointers();
InitFSFunctionPointers();
log_init();
@ -42,20 +54,104 @@ extern "C" int Menu_Main(int argc, char **argv){
setup_os_exceptions();
DEBUG_FUNCTION_LINE("End address of loader %08X\n",getApplicationEndAddr());
if(isFirstBoot){
memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
loadSamplePlugin();
}
memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
CallHook(WUPS_LOADER_HOOK_INIT_FUNCTION);
DEBUG_FUNCTION_LINE("Apply patches.\n");
ApplyPatches();
//Reset everything when were going back to the Mii Maker
if(!isFirstBoot && isInMiiMakerHBL()){
DEBUG_FUNCTION_LINE("Returing to the Homebrew Launcher!\n");
isFirstBoot = 0;
RestorePatches();
return EXIT_SUCCESS;
}
if(!isInMiiMakerHBL()){ //Starting the application
return EXIT_RELAUNCH_ON_LOAD;
}
if(isFirstBoot){ // First boot back to SysMenu
DEBUG_FUNCTION_LINE("Loading the System Menu\n");
isFirstBoot = 0;
SYSLaunchMenu();
return EXIT_RELAUNCH_ON_LOAD;
}
DEBUG_FUNCTION_LINE("Application is ending now.\n");
RestorePatches();
return EXIT_SUCCESS;
}
void ApplyPatches(){
for(int module_index=0;module_index<gbl_replacement_data.number_used_modules;module_index++){
new_PatchInvidualMethodHooks(&gbl_replacement_data.module_data[module_index]);
}
}
void CallHook(wups_loader_hook_type_t hook_type){
for(int module_index=0;module_index<gbl_replacement_data.number_used_modules;module_index++){
replacement_data_module_t * module_data = &gbl_replacement_data.module_data[module_index];
DEBUG_FUNCTION_LINE("Checking hook functions for %s.\n",module_data->module_name);
DEBUG_FUNCTION_LINE("Found hooks: %d\n",module_data->number_used_hooks);
for(int j=0;j<module_data->number_used_hooks;j++){
replacement_data_hook_t * hook_data = &module_data->hooks[j];
if(hook_data->type == hook_type){
DEBUG_FUNCTION_LINE("Calling hook of type %d\n",hook_data->type);
void * func_ptr = hook_data->func_pointer;
//TODO: Switch cases depending on arguments etc.
if(func_ptr != NULL){
DEBUG_FUNCTION_LINE("Calling it! %08X\n",func_ptr);
( (void (*)(void))((unsigned int*)func_ptr) )();
}else{
DEBUG_FUNCTION_LINE("Was not defined\n");
}
}
}
}
}
void RestorePatches(){
for(int module_index=0;module_index<gbl_replacement_data.number_used_modules;module_index++){
new_RestoreInvidualInstructions(&gbl_replacement_data.module_data[module_index]);
}
}
s32 isInMiiMakerHBL(){
if (OSGetTitleID != 0 && (
OSGetTitleID() == 0x000500101004A200 || // mii maker eur
OSGetTitleID() == 0x000500101004A100 || // mii maker usa
OSGetTitleID() == 0x000500101004A000 ||// mii maker jpn
OSGetTitleID() == 0x0005000013374842))
{
return 1;
}
return 0;
}
void loadSamplePlugin(){
DEBUG_FUNCTION_LINE("Mount SD partition\n");
int res = 0;
if((res = mount_sd_fat("sd")) >= 0){
DEBUG_FUNCTION_LINE("Mounting successful\n");
loadElf("sd:/wiiu/plugins/example_plugin.mod");
loadElf("sd:/wiiu/plugins/padcon.mod");
if(module_list_count == 0){
DEBUG_FUNCTION_LINE("Found no valid modules! =( Exiting\n");
return EXIT_SUCCESS;
return;
}
DEBUG_FUNCTION_LINE("Found %d modules!\n",module_list_count);
@ -81,12 +177,6 @@ extern "C" int Menu_Main(int argc, char **argv){
printReplacementInfos();
for(int module_index=0;module_index<gbl_replacement_data.number_used_modules;module_index++){
new_PatchInvidualMethodHooks(&gbl_replacement_data.module_data[module_index]);
}
// The example plugin should override the message.
OSFatal("We should never see this message.");
/*
test code for calling the loaded functions.
@ -105,10 +195,6 @@ extern "C" int Menu_Main(int argc, char **argv){
}*/
}
DEBUG_FUNCTION_LINE("Application is ending now.\n");
return EXIT_SUCCESS;
}
void loadElf(const char * elfPath){

View File

@ -220,7 +220,10 @@ static void Module_LoadElf(const char *path, Elf *elf) {
continue;
} else if (strcmp(name, ".wups.load") == 0) {
metadata->size +=
shdr->sh_size / sizeof(wups_loader_entry_t) * 12;
shdr->sh_size / sizeof(wups_loader_entry_t) * 6*4;
} else if (strcmp(name, ".wups.hooks") == 0) {
metadata->size +=
shdr->sh_size / sizeof(wups_loader_hook_t) * 2*4;
} else {
metadata->size += shdr->sh_size;
/* add alignment padding to size */

View File

@ -55,6 +55,14 @@ struct replacement_data_function_t{
};
struct replacement_data_hook_t{
void * func_pointer = NULL; /* [will be filled] */
wups_loader_hook_type_t type; /* [will be filled] */
u32 hook_index; /* [needs to be filled] name of the function we want to replace */
};
#define MAXIMUM_HOOKS_PER_MODULE 4
#define MAXIMUM_FUNCTION_PER_MODULE 100
struct replacement_data_module_t{
@ -62,6 +70,9 @@ struct replacement_data_module_t{
int priority; // Priority of this module
int number_used_functions; // Number of used function. Maximum is MAXIMUM_FUNCTION_PER_MODULE
replacement_data_function_t functions[MAXIMUM_FUNCTION_PER_MODULE]; // Replacement information for each function.
int number_used_hooks; // Number of used hooks. Maximum is MAXIMUM_HOOKS_PER_MODULE
replacement_data_hook_t hooks[MAXIMUM_HOOKS_PER_MODULE]; // Replacement information for each function.
};
#define MAXIMUM_MODULES 32