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-26 14:17:50 +01:00
# include "utils/logger.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-05-03 14:14:22 +02:00
std : : vector < PluginContainer > loadPlugins ( const std : : vector < PluginData > & pluginList , MEMHeapHandle heapHandle ) ;
2020-05-03 12:37:20 +02:00
2020-06-06 22:10:41 +02:00
WUMS_INITIALIZE ( args ) {
2020-12-26 13:27:50 +01:00
__init_wut ( ) ;
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 " ) ;
__fini_wut ( ) ;
2020-04-29 18:02:36 +02:00
}
2020-06-03 18:21:43 +02:00
WUMS_APPLICATION_STARTS ( ) {
2020-12-26 13:27:50 +01:00
__init_wut ( ) ;
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 ;
DEBUG_FUNCTION_LINE ( " endAddress: %08X " , endAddress ) ;
DEBUG_FUNCTION_LINE ( " Create heap " ) ;
2020-05-03 10:21:05 +02:00
pluginDataHeap = MEMCreateExpHeapEx ( ( void * ) ( endAddress ) , 0x00FFF000 - endAddress , 0 ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 10:21:05 +02:00
if ( pluginDataHeap ! = NULL ) {
if ( gPluginInformation = = NULL ) {
gPluginInformation = ( plugin_information_t * ) MEMAllocFromExpHeapEx ( pluginDataHeap , sizeof ( plugin_information_t ) , 4 ) ;
if ( gPluginInformation = = NULL ) {
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-05-03 11:13:55 +02:00
2020-04-29 18:02:36 +02:00
}
2020-05-03 10:21:05 +02:00
DEBUG_FUNCTION_LINE ( " MEMGetAllocatableSizeForExpHeapEx %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 ) ;
DEBUG_FUNCTION_LINE ( " Loaded %d plugin data " , 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 ) {
DEBUG_FUNCTION_LINE ( " We would now swap the plugins " ) ;
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 ;
DEBUG_FUNCTION_LINE ( " Check if we can delete %08X " , plugin - > data . buffer ) ;
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
DEBUG_FUNCTION_LINE ( " We can keep buffer %08X " , plugin - > data . buffer ) ;
doDelete = false ;
break ;
}
}
if ( doDelete ) {
if ( plugin - > data . buffer ! = nullptr ) {
if ( plugin - > data . memoryType = = eMemTypeMEM2 ) {
DEBUG_FUNCTION_LINE ( " free %08X " , plugin - > data . buffer ) ;
free ( plugin - > data . buffer ) ;
} else if ( plugin - > data . memoryType = = eMemTypeExpHeap ) {
DEBUG_FUNCTION_LINE ( " free %08X on EXP heap %08X " , plugin - > data . buffer , plugin - > data . heapHandle ) ;
MEMFreeToExpHeap ( ( MEMHeapHandle ) plugin - > data . heapHandle , plugin - > data . buffer ) ;
} else {
DEBUG_FUNCTION_LINE ( " ######################## " ) ;
DEBUG_FUNCTION_LINE ( " Failed to free memory from plugin " ) ;
DEBUG_FUNCTION_LINE ( " ######################## " ) ;
}
plugin - > data . buffer = NULL ;
plugin - > data . bufferLength = 0 ;
} else {
DEBUG_FUNCTION_LINE ( " Plugin has no copy of elf save in memory, can't free it " ) ;
}
}
}
DEBUG_FUNCTION_LINE ( " unloadPlugins " ) ;
PluginManagement : : unloadPlugins ( gPluginInformation , pluginDataHeap , false ) ;
std : : vector < PluginContainer > plugins = PluginManagement : : loadPlugins ( pluginDataList , pluginDataHeap , gPluginInformation - > trampolines , DYN_LINK_TRAMPOLIN_LIST_LENGTH ) ;
for ( auto & pluginContainer : plugins ) {
DEBUG_FUNCTION_LINE ( " Saving %s from %s " , pluginContainer . getMetaInformation ( ) . getName ( ) . c_str ( ) , pluginContainer . getMetaInformation ( ) . getAuthor ( ) . c_str ( ) ) ;
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
2020-05-03 10:21:05 +02:00
if ( pluginDataHeap ! = NULL ) {
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
2020-05-03 10:21:05 +02:00
DCFlushRange ( ( void * ) 0x00800000 , 0x00800000 ) ;
ICInvalidateRange ( ( void * ) 0x00800000 , 0x00800000 ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 10:21:05 +02:00
if ( initNeeded ) {
PluginManagement : : callInitHooks ( gPluginInformation ) ;
initNeeded = false ;
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
}
2020-06-03 18:21:43 +02:00
return ;
2020-04-29 18:02:36 +02:00
}