mirror of
https://github.com/wiiu-env/WiiUPluginSystem.git
synced 2025-01-27 16:25:38 +01:00
dc8a9a81fc
- Now patching two more function which could be used as hooks (PPCExit and ProcUIProcessMessages)
360 lines
13 KiB
C++
360 lines
13 KiB
C++
#include <string>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <malloc.h>
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
|
|
|
|
#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>
|
|
#include <utils/utils.h>
|
|
#include <system/exception_handler.h>
|
|
|
|
#include "common/retain_vars.h"
|
|
#include "common/common.h"
|
|
#include "ModuleData.h"
|
|
|
|
#include <utils/function_patcher.h>
|
|
|
|
#include <wups.h>
|
|
#include <iosuhax.h>
|
|
#include <fat.h>
|
|
#include <ntfs.h>
|
|
|
|
#include "main.h"
|
|
#include "utils.h"
|
|
#include "patcher/function_patcher.h"
|
|
#include "patcher/hooks_patcher.h"
|
|
#include "myutils/mocha.h"
|
|
#include "myutils/libntfs.h"
|
|
#include "myutils/libfat.h"
|
|
#include "version.h"
|
|
|
|
static bool loadSamplePlugins();
|
|
static void ApplyPatches();
|
|
void CallHook(wups_loader_hook_type_t hook_type);
|
|
static void RestorePatches();
|
|
s32 isInMiiMakerHBL();
|
|
|
|
static void copyDataIntoGlobalStruct(std::vector<ModuleData *>* modules);
|
|
static void loadElf(std::vector<ModuleData *>* modules, const char * elfPath, uint8_t ** space);
|
|
|
|
u8 isFirstBoot __attribute__((section(".data"))) = 1;
|
|
|
|
/* Entry point */
|
|
extern "C" int Menu_Main(int argc, char **argv){
|
|
if(gAppStatus == 2){
|
|
//"No, we don't want to patch stuff again.");
|
|
return EXIT_RELAUNCH_ON_LOAD;
|
|
}
|
|
InitOSFunctionPointers();
|
|
InitSocketFunctionPointers(); //For logging
|
|
InitSysFunctionPointers();
|
|
InitFSFunctionPointers();
|
|
|
|
log_init();
|
|
|
|
DEBUG_FUNCTION_LINE("Wii U Plugin System Loader %s\n",APP_VERSION);
|
|
|
|
setup_os_exceptions();
|
|
|
|
DEBUG_FUNCTION_LINE("Mount SD partition\n");
|
|
Init_SD_USB();
|
|
|
|
if(isFirstBoot){
|
|
memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
|
|
if(!loadSamplePlugins()){
|
|
return EXIT_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//Reset everything when were going back to the Mii Maker
|
|
if(!isFirstBoot && isInMiiMakerHBL()){
|
|
DEBUG_FUNCTION_LINE("Returing to the Homebrew Launcher!\n");
|
|
isFirstBoot = 0;
|
|
DeInit();
|
|
RestorePatches();
|
|
return EXIT_SUCCESS;
|
|
} else {
|
|
DEBUG_FUNCTION_LINE("Apply patches.\n");
|
|
ApplyPatches();
|
|
}
|
|
|
|
if(!isInMiiMakerHBL()){ //Starting the application
|
|
DEBUG_FUNCTION_LINE("Calling init hook.\n");
|
|
CallHook(WUPS_LOADER_HOOK_INIT_FUNCTION);
|
|
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");
|
|
|
|
DeInit();
|
|
RestorePatches();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
void ApplyPatches(){
|
|
PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks);
|
|
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.
|
|
// Adding arguments!
|
|
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 DeInit(){
|
|
DeInit_SD_USB();
|
|
}
|
|
|
|
void RestorePatches(){
|
|
for(int module_index=gbl_replacement_data.number_used_modules-1;module_index>=0;module_index--){
|
|
DEBUG_FUNCTION_LINE("Restoring function for module: %d\n",module_index);
|
|
new_RestoreInvidualInstructions(&gbl_replacement_data.module_data[module_index]);
|
|
}
|
|
RestoreInvidualInstructions(method_hooks_hooks, method_hooks_size_hooks);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#define PLUGIN_LOCATION_END_ADDRESS 0x01000000
|
|
|
|
bool loadSamplePlugins(){
|
|
if((gSDInitDone & (SDUSB_MOUNTED_OS_SD | SD_MOUNTED_LIBFAT)) > 0){
|
|
DEBUG_FUNCTION_LINE("Mounting successful. Loading modules\n");
|
|
|
|
std::vector<ModuleData *> modules;
|
|
|
|
// Set a pointer to the END of our plugin location.
|
|
// So our plugins will be stored from PLUGIN_LOCATION_END_ADDRESS backward. Maximum is getApplicationEndAddr() (behind this loader).
|
|
// Copied the "reserved" direction from brainslug, not sure why we're doing this.
|
|
unsigned char * space = (unsigned char*)PLUGIN_LOCATION_END_ADDRESS;
|
|
|
|
|
|
// TODO: Load all files from a certain directory, don't use hardcoded paths. (common.h)
|
|
loadElf(&modules, "sd:/wiiu/plugins/hid_to_vpad.mod",&space);
|
|
loadElf(&modules, "sd:/wiiu/plugins/sdcafiine.mod",&space);
|
|
loadElf(&modules, "sd:/wiiu/plugins/padcon.mod",&space);
|
|
loadElf(&modules, "sd:/wiiu/plugins/swipswapme.mod",&space);
|
|
|
|
// Copy the data into the global struct locating in the .data section.
|
|
copyDataIntoGlobalStruct(&modules);
|
|
|
|
// Free memory.
|
|
for(size_t i = 0; i< modules.size();i++){
|
|
ModuleData * cur_module = modules[i];
|
|
if(cur_module != NULL){
|
|
free(cur_module);
|
|
}
|
|
}
|
|
|
|
DEBUG_FUNCTION_LINE("Flush memory\n");
|
|
DCFlushRange ((void*)getApplicationEndAddr(),PLUGIN_LOCATION_END_ADDRESS-getApplicationEndAddr());
|
|
DCInvalidateRange((void*)getApplicationEndAddr(),PLUGIN_LOCATION_END_ADDRESS-getApplicationEndAddr());
|
|
|
|
// TODO: keep it mounted for the plugins. But this would require sharing the read/write/open etc. functions from this loader.
|
|
// Idea: Giving the init hook the pointers. Hiding the __wrap function of the plugin behind the INITIALIZE macro.
|
|
// Needs to be tested if this is working. This would have the advantage of adopting all right/accesses from the loader (libfat, libntfs, iosuhax etc.)
|
|
//unmount_sd_fat("sd");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void copyDataIntoGlobalStruct(std::vector<ModuleData *>* modules){
|
|
int module_index = 0;
|
|
// Copy data to global struct.
|
|
for(size_t i = 0; i< modules->size();i++){
|
|
ModuleData * cur_module = modules->at(i);
|
|
|
|
std::vector<EntryData *> entry_data_list = cur_module->getEntryDataList();
|
|
std::vector<HookData *> hook_data_list = cur_module->getHookDataList();
|
|
if(module_index >= MAXIMUM_MODULES ){
|
|
DEBUG_FUNCTION_LINE("Maximum of %d modules reached. %s won't be loaded!\n",MAXIMUM_MODULES,cur_module->getName().c_str());
|
|
continue;
|
|
}
|
|
if(entry_data_list.size() > MAXIMUM_FUNCTION_PER_MODULE){
|
|
DEBUG_FUNCTION_LINE("Module %s would replace to many function (%d, maximum is %d). It won't be loaded.\n",cur_module->getName().c_str(),entry_data_list.size(),MAXIMUM_FUNCTION_PER_MODULE);
|
|
continue;
|
|
}
|
|
if(hook_data_list.size() > MAXIMUM_HOOKS_PER_MODULE){
|
|
DEBUG_FUNCTION_LINE("Module %s would set too many hooks (%d, maximum is %d). It won't be loaded.\n",cur_module->getName().c_str(),hook_data_list.size(),MAXIMUM_HOOKS_PER_MODULE);
|
|
continue;
|
|
}
|
|
|
|
replacement_data_module_t * module_data = &gbl_replacement_data.module_data[module_index];
|
|
|
|
strncpy(module_data->module_name,cur_module->getName().c_str(),MAXIMUM_MODULE_NAME_LENGTH-1);
|
|
|
|
for(size_t j = 0; j < entry_data_list.size();j++){
|
|
replacement_data_function_t * function_data = &module_data->functions[j];
|
|
|
|
EntryData * cur_entry = entry_data_list[j];
|
|
DEBUG_FUNCTION_LINE("Adding entry \"%s\" for module \"%s\"\n",cur_entry->getName().c_str(),module_data->module_name);
|
|
|
|
//TODO: Warning/Error if string is too long.
|
|
strncpy(function_data->function_name,cur_entry->getName().c_str(),MAXIMUM_FUNCTION_NAME_LENGTH-1);
|
|
|
|
function_data->library = cur_entry->getLibrary();
|
|
function_data->replaceAddr = (u32) cur_entry->getReplaceAddress();
|
|
function_data->replaceCall = (u32) cur_entry->getReplaceCall();
|
|
|
|
module_data->number_used_functions++;
|
|
}
|
|
|
|
DEBUG_FUNCTION_LINE("Entries for module \"%s\": %d\n",module_data->module_name,module_data->number_used_functions);
|
|
|
|
for(size_t j = 0; j < hook_data_list.size();j++){
|
|
replacement_data_hook_t * hook_data = &module_data->hooks[j];
|
|
|
|
HookData * hook_entry = hook_data_list[j];
|
|
|
|
DEBUG_FUNCTION_LINE("Set hook for module \"%s\" of type %08X to target %08X\n",module_data->module_name,hook_entry->getType(),(void*) hook_entry->getFunctionPointer());
|
|
hook_data->func_pointer = (void*) hook_entry->getFunctionPointer();
|
|
hook_data->type = hook_entry->getType();
|
|
module_data->number_used_hooks++;
|
|
}
|
|
|
|
DEBUG_FUNCTION_LINE("Hooks for module \"%s\": %d\n",module_data->module_name,module_data->number_used_hooks);
|
|
|
|
module_index++;
|
|
gbl_replacement_data.number_used_modules++;
|
|
}
|
|
}
|
|
|
|
static void loadElf(std::vector<ModuleData *>* modules, const char * elfPath, uint8_t ** space){
|
|
DEBUG_FUNCTION_LINE("Try to load %s\n",elfPath);
|
|
|
|
ModuleData * module = new ModuleData(elfPath,space);
|
|
if(module->isLoadedSuccessfully()){
|
|
DEBUG_FUNCTION_LINE("%s loading was successful!. \n", elfPath);
|
|
modules->push_back(module);
|
|
} else {
|
|
DEBUG_FUNCTION_LINE("%s loading failed. \n", elfPath);
|
|
}
|
|
}
|
|
|
|
void Init_SD_USB() {
|
|
int res = IOSUHAX_Open(NULL);
|
|
if(res < 0){
|
|
ExecuteIOSExploitWithDefaultConfig();
|
|
}
|
|
deleteDevTabsNames();
|
|
mount_fake();
|
|
gSDInitDone |= SDUSB_MOUNTED_FAKE;
|
|
|
|
if(res < 0){
|
|
DEBUG_FUNCTION_LINE("IOSUHAX_open failed\n");
|
|
if((res = mount_sd_fat("sd")) >= 0){
|
|
DEBUG_FUNCTION_LINE("mount_sd_fat success\n");
|
|
gSDInitDone |= SDUSB_MOUNTED_OS_SD;
|
|
}else{
|
|
DEBUG_FUNCTION_LINE("mount_sd_fat failed %d\n",res);
|
|
}
|
|
}else{
|
|
DEBUG_FUNCTION_LINE("Using IOSUHAX for SD/USB access\n");
|
|
gSDInitDone |= SDUSB_LIBIOSU_LOADED;
|
|
int ntfs_mounts = mountAllNTFS();
|
|
if(ntfs_mounts > 0){
|
|
gSDInitDone |= USB_MOUNTED_LIBNTFS;
|
|
}
|
|
|
|
if(mount_libfatAll() == 0){
|
|
gSDInitDone |= SD_MOUNTED_LIBFAT;
|
|
gSDInitDone |= USB_MOUNTED_LIBFAT;
|
|
}
|
|
}
|
|
DEBUG_FUNCTION_LINE("%08X\n",gSDInitDone);
|
|
}
|
|
|
|
void DeInit_SD_USB(){
|
|
DEBUG_FUNCTION_LINE("Called this function.\n");
|
|
|
|
if(gSDInitDone & SDUSB_MOUNTED_FAKE){
|
|
DEBUG_FUNCTION_LINE("Unmounting fake\n");
|
|
unmount_fake();
|
|
gSDInitDone &= ~SDUSB_MOUNTED_FAKE;
|
|
}
|
|
if(gSDInitDone & SDUSB_MOUNTED_OS_SD){
|
|
DEBUG_FUNCTION_LINE("Unmounting OS SD\n");
|
|
unmount_sd_fat("sd");
|
|
gSDInitDone &= ~SDUSB_MOUNTED_OS_SD;
|
|
}
|
|
|
|
if(gSDInitDone & SD_MOUNTED_LIBFAT){
|
|
DEBUG_FUNCTION_LINE("Unmounting LIBFAT SD\n");
|
|
unmount_libfat("sd");
|
|
gSDInitDone &= ~SD_MOUNTED_LIBFAT;
|
|
}
|
|
|
|
if(gSDInitDone & USB_MOUNTED_LIBFAT){
|
|
DEBUG_FUNCTION_LINE("Unmounting LIBFAT USB\n");
|
|
unmount_libfat("usb");
|
|
gSDInitDone &= ~USB_MOUNTED_LIBFAT;
|
|
}
|
|
|
|
if(gSDInitDone & USB_MOUNTED_LIBNTFS){
|
|
DEBUG_FUNCTION_LINE("Unmounting LIBNTFS USB\n");
|
|
unmountAllNTFS();
|
|
gSDInitDone &= ~USB_MOUNTED_LIBNTFS;
|
|
}
|
|
|
|
if(gSDInitDone & SDUSB_LIBIOSU_LOADED){
|
|
DEBUG_FUNCTION_LINE("Calling IOSUHAX_Close\n");
|
|
IOSUHAX_Close();
|
|
gSDInitDone &= ~SDUSB_LIBIOSU_LOADED;
|
|
|
|
}
|
|
deleteDevTabsNames();
|
|
if(gSDInitDone != SDUSB_MOUNTED_NONE){
|
|
DEBUG_FUNCTION_LINE("WARNING. Some devices are still mounted.\n");
|
|
}
|
|
DEBUG_FUNCTION_LINE("Function end.\n");
|
|
}
|