2020-04-29 18:02:36 +02:00
# include <whb/log_udp.h>
2020-12-26 14:17:50 +01:00
# include <wums.h>
2020-05-28 20:49:52 +02:00
# include <coreinit/debug.h>
2020-04-29 18:02:36 +02:00
# include <coreinit/cache.h>
2020-12-26 14:17:50 +01:00
# include "plugin/PluginContainer.h"
# include "globals.h"
2020-04-29 18:02:36 +02:00
# include "plugin/PluginDataFactory.h"
2020-12-26 14:17:50 +01:00
# include "plugin/PluginDataPersistence.h"
2020-04-29 18:02:36 +02:00
# include "plugin/PluginContainerPersistence.h"
2020-05-03 10:21:05 +02:00
# include "PluginManagement.h"
2020-12-28 14:38:08 +01:00
# include "hooks.h"
2020-12-28 14:38:49 +01:00
# include "patcher/hooks_patcher_static.h"
2020-04-29 18:02:36 +02:00
2020-05-17 21:08:13 +02:00
WUMS_MODULE_EXPORT_NAME ( " homebrew_wupsbackend " ) ;
2020-04-29 18:02:36 +02:00
2020-06-06 22:10:41 +02:00
WUMS_INITIALIZE ( args ) {
2020-12-26 13:27:50 +01:00
WHBLogUdpInit ( ) ;
2020-12-26 14:17:50 +01:00
2020-06-06 22:10:41 +02:00
gModuleData = args . module_information ;
2020-12-26 14:17:50 +01:00
if ( gModuleData = = nullptr ) {
2020-06-07 14:10:31 +02:00
OSFatal ( " WUPS-Backend: Failed to get gModuleData pointer. " ) ;
}
2020-12-26 14:17:50 +01:00
if ( gModuleData - > version ! = MODULE_INFORMATION_VERSION ) {
2020-06-07 14:10:31 +02:00
OSFatal ( " WUPS-Backend: The module information struct version does not match. " ) ;
}
2020-12-26 13:27:50 +01:00
WHBLogPrintf ( " Init successful " ) ;
2020-12-28 14:38:08 +01:00
}
WUMS_APPLICATION_ENDS ( ) {
2020-12-28 14:38:49 +01:00
DEBUG_FUNCTION_LINE ( " Reset alreadyPatched flags for dynamic functions " ) ;
auto pluginInformation = gPluginInformation ;
for ( int32_t plugin_index = pluginInformation - > number_used_plugins - 1 ; plugin_index > = 0 ; plugin_index - - ) {
FunctionPatcherRestoreDynamicFunctions ( pluginInformation - > plugin_data [ plugin_index ] . info . functions , pluginInformation - > plugin_data [ plugin_index ] . info . number_used_functions ) ;
}
FunctionPatcherRestoreDynamicFunctions ( method_hooks_hooks_static , method_hooks_size_hooks_static ) ;
2020-12-28 14:38:08 +01:00
DEBUG_FUNCTION_LINE ( " Call hooks " ) ;
CallHook ( gPluginInformation , WUPS_LOADER_HOOK_APPLICATION_END ) ;
CallHook ( gPluginInformation , WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB ) ;
2020-04-29 18:02:36 +02:00
}
2020-06-03 18:21:43 +02:00
WUMS_APPLICATION_STARTS ( ) {
2020-04-29 18:02:36 +02:00
WHBLogUdpInit ( ) ;
2020-05-28 20:49:52 +02:00
uint32_t upid = OSGetUPID ( ) ;
if ( upid ! = 2 & & upid ! = 15 ) {
2020-06-03 18:21:43 +02:00
return ;
2020-05-28 20:49:52 +02:00
}
2020-05-03 10:21:05 +02:00
bool initNeeded = false ;
2020-12-26 14:17:50 +01:00
if ( pluginDataHeap = = nullptr ) {
2020-06-06 22:10:41 +02:00
DEBUG_FUNCTION_LINE ( " gModuleData = %08X " , gModuleData ) ;
DCFlushRange ( ( void * ) gModuleData , sizeof ( module_information_t ) ) ;
2020-04-29 18:02:36 +02:00
uint32_t endAddress = 0 ;
2020-05-03 10:21:05 +02:00
DEBUG_FUNCTION_LINE ( " Using %d modules " , gModuleData - > number_used_modules ) ;
for ( int i = 0 ; i < gModuleData - > number_used_modules ; i + + ) {
DEBUG_FUNCTION_LINE ( " %08x " , gModuleData - > module_data [ i ] . endAddress ) ;
2020-04-29 18:02:36 +02:00
uint32_t curEndAddr = gModuleData - > module_data [ i ] . endAddress ;
2020-05-03 10:21:05 +02:00
if ( curEndAddr > endAddress ) {
2020-04-29 18:02:36 +02:00
endAddress = curEndAddr ;
}
}
2020-05-17 20:49:31 +02:00
memset ( ( void * ) & gLinkOnReload , 0 , sizeof ( gLinkOnReload ) ) ;
2020-04-29 18:02:36 +02:00
// If this address is 0, make sure the header common match the one
2020-05-03 10:21:05 +02:00
// in the SetupPayload repo. (I know that's a bad idea)
2020-04-29 18:02:36 +02:00
endAddress = ( endAddress + 0x100 ) & 0xFFFFFF00 ;
2021-01-10 13:17:47 +01:00
gPluginDataHeapSize = 0x00FFF000 - endAddress ;
DEBUG_FUNCTION_LINE ( " Create heap to store plugins " ) ;
pluginDataHeap = MEMCreateExpHeapEx ( ( void * ) ( endAddress ) , gPluginDataHeapSize , 0 ) ;
2020-04-29 18:02:36 +02:00
2021-01-10 13:17:47 +01:00
if ( pluginDataHeap ! = nullptr ) {
if ( gPluginInformation = = nullptr ) {
DEBUG_FUNCTION_LINE ( " Allocate gPluginInformation on heap %08X (size: %d bytes) " , pluginDataHeap , sizeof ( plugin_information_t ) ) ;
2020-05-03 10:21:05 +02:00
gPluginInformation = ( plugin_information_t * ) MEMAllocFromExpHeapEx ( pluginDataHeap , sizeof ( plugin_information_t ) , 4 ) ;
2021-01-10 13:17:47 +01:00
if ( gPluginInformation = = nullptr ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Failed to allocate global plugin information " ) ;
2020-06-03 18:21:43 +02:00
return ;
2020-04-29 18:02:36 +02:00
}
2020-05-03 10:21:05 +02:00
memset ( ( void * ) gPluginInformation , 0 , sizeof ( plugin_information_t ) ) ;
2020-04-29 18:02:36 +02:00
}
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " Available memory for storing plugins: %d kb " , MEMGetAllocatableSizeForExpHeapEx ( pluginDataHeap , 4 ) / 1024 ) ;
2020-04-29 18:02:36 +02:00
std : : vector < PluginData > pluginList = PluginDataFactory : : loadDir ( " fs:/vol/external01/wiiu/plugins/ " , pluginDataHeap ) ;
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " Loaded data for %d plugins. " , pluginList . size ( ) ) ;
2020-05-03 11:13:55 +02:00
2020-05-03 14:20:00 +02:00
std : : vector < PluginContainer > plugins = PluginManagement : : loadPlugins ( pluginList , pluginDataHeap , gPluginInformation - > trampolines , DYN_LINK_TRAMPOLIN_LIST_LENGTH ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:37:20 +02:00
for ( auto & pluginContainer : plugins ) {
for ( const auto & kv : pluginContainer . getPluginInformation ( ) . getSectionInfoList ( ) ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " %s = %s %08X %d " , kv . first . c_str ( ) , kv . second . getName ( ) . c_str ( ) , kv . second . getAddress ( ) , kv . second . getSize ( ) ) ;
}
2020-05-03 10:21:05 +02:00
if ( ! PluginContainerPersistence : : savePlugin ( gPluginInformation , pluginContainer ) ) {
DEBUG_FUNCTION_LINE ( " Failed to save plugin " ) ;
}
2020-04-29 18:02:36 +02:00
}
2020-05-03 10:21:05 +02:00
initNeeded = true ;
2020-04-29 18:02:36 +02:00
}
}
2020-05-17 20:49:31 +02:00
if ( gLinkOnReload . loadOnReload ) {
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " Reload with new plugin list. " ) ;
2020-05-17 20:49:31 +02:00
std : : vector < PluginData > pluginDataList ;
for ( int32_t i = 0 ; i < gLinkOnReload . number_used_plugins ; i + + ) {
auto pluginData = PluginDataPersistence : : load ( & gLinkOnReload . plugin_data [ i ] ) ;
pluginDataList . push_back ( pluginData ) ;
}
for ( int32_t plugin_index = 0 ; plugin_index < gPluginInformation - > number_used_plugins ; plugin_index + + ) {
plugin_information_single_t * plugin = & ( gPluginInformation - > plugin_data [ plugin_index ] ) ;
BOOL doDelete = true ;
for ( auto & pluginData : pluginDataList ) {
2020-06-03 18:34:31 +02:00
if ( pluginData . buffer = = plugin - > data . buffer ) {
2020-05-17 20:49:31 +02:00
doDelete = false ;
break ;
}
}
if ( doDelete ) {
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " We need to delete the plugin data for plugin %s " , plugin - > meta . name ) ;
2020-05-17 20:49:31 +02:00
if ( plugin - > data . buffer ! = nullptr ) {
if ( plugin - > data . memoryType = = eMemTypeMEM2 ) {
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " Free plugin data buffer for %s [%08X] " , plugin - > meta . name , plugin - > data . buffer ) ;
2020-05-17 20:49:31 +02:00
free ( plugin - > data . buffer ) ;
} else if ( plugin - > data . memoryType = = eMemTypeExpHeap ) {
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " Free plugin data buffer for %s [%08X on heap %08X] " , plugin - > meta . name , plugin - > data . buffer , plugin - > data . heapHandle ) ;
2020-05-17 20:49:31 +02:00
MEMFreeToExpHeap ( ( MEMHeapHandle ) plugin - > data . heapHandle , plugin - > data . buffer ) ;
} else {
DEBUG_FUNCTION_LINE ( " ######################## " ) ;
DEBUG_FUNCTION_LINE ( " Failed to free memory from plugin " ) ;
DEBUG_FUNCTION_LINE ( " ######################## " ) ;
}
2021-01-10 13:17:47 +01:00
plugin - > data . buffer = nullptr ;
2020-05-17 20:49:31 +02:00
plugin - > data . bufferLength = 0 ;
} else {
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " Plugin %s has no copy of elf saved in memory, can't free it " , plugin - > meta . name ) ;
2020-05-17 20:49:31 +02:00
}
}
}
PluginManagement : : unloadPlugins ( gPluginInformation , pluginDataHeap , false ) ;
std : : vector < PluginContainer > plugins = PluginManagement : : loadPlugins ( pluginDataList , pluginDataHeap , gPluginInformation - > trampolines , DYN_LINK_TRAMPOLIN_LIST_LENGTH ) ;
for ( auto & pluginContainer : plugins ) {
2021-01-10 13:17:47 +01:00
DEBUG_FUNCTION_LINE ( " Stored information for plugin %s ; %s " , pluginContainer . getMetaInformation ( ) . getName ( ) . c_str ( ) , pluginContainer . getMetaInformation ( ) . getAuthor ( ) . c_str ( ) ) ;
2020-05-17 20:49:31 +02:00
if ( ! PluginContainerPersistence : : savePlugin ( gPluginInformation , pluginContainer ) ) {
DEBUG_FUNCTION_LINE ( " Failed to save plugin " ) ;
}
}
gLinkOnReload . loadOnReload = false ;
initNeeded = true ;
}
2020-04-29 18:02:36 +02:00
2021-01-10 13:17:47 +01:00
if ( pluginDataHeap ! = nullptr ) {
2020-04-29 18:02:36 +02:00
std : : vector < PluginContainer > plugins = PluginContainerPersistence : : loadPlugins ( gPluginInformation ) ;
2020-05-03 10:21:05 +02:00
PluginManagement : : doRelocations ( plugins , gPluginInformation - > trampolines , DYN_LINK_TRAMPOLIN_LIST_LENGTH ) ;
2020-06-03 19:33:09 +02:00
// PluginManagement::memsetBSS(plugins);
2020-04-29 18:02:36 +02:00
2021-01-10 13:17:47 +01:00
DCFlushRange ( ( void * ) pluginDataHeap , gPluginDataHeapSize ) ;
ICInvalidateRange ( ( void * ) pluginDataHeap , gPluginDataHeapSize ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 10:21:05 +02:00
if ( initNeeded ) {
PluginManagement : : callInitHooks ( gPluginInformation ) ;
2020-04-29 18:02:36 +02:00
}
2020-05-03 10:21:05 +02:00
PluginManagement : : PatchFunctionsAndCallHooks ( gPluginInformation ) ;
2020-04-29 18:02:36 +02:00
}
}