diff --git a/loader/src/link_utils.cpp b/loader/src/link_utils.cpp index ffd190f..bd2998c 100644 --- a/loader/src/link_utils.cpp +++ b/loader/src/link_utils.cpp @@ -40,8 +40,16 @@ #include #include +//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_indexmodule_name); + for(int j=0;jnumber_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;jnumber_used_functions;j++){ replacement_data_function_t * function_data = &module_data->functions[j]; diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 44245be..13bef72 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -7,7 +7,9 @@ #include #include +#include #include +#include #include #include #include @@ -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_indexmodule_name); + DEBUG_FUNCTION_LINE("Found hooks: %d\n",module_data->number_used_hooks); + for(int j=0;jnumber_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= 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_indexsize += - 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 */ diff --git a/loader/src/patcher/function_patcher.h b/loader/src/patcher/function_patcher.h index 92dc8f0..e2feaaf 100644 --- a/loader/src/patcher/function_patcher.h +++ b/loader/src/patcher/function_patcher.h @@ -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