CustomRPXLoader/src/main.cpp

147 lines
5.3 KiB
C++
Raw Normal View History

2020-08-23 12:59:52 +02:00
/****************************************************************************
* Copyright (C) 2018-2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
2020-04-27 13:32:37 +02:00
#include <stdint.h>
#include <coreinit/cache.h>
#include <coreinit/dynload.h>
#include <sysapp/launch.h>
#include <nsysnet/socket.h>
#include <proc_ui/procui.h>
#include <coreinit/foreground.h>
#include "ElfUtils.h"
#include "module/ModuleData.h"
#include "module/ModuleDataFactory.h"
#include "common/module_defines.h"
#include <whb/log.h>
#include <whb/log_udp.h>
2020-04-27 13:32:37 +02:00
#include "kernel.h"
#include "dynamic.h"
#include "utils/logger.h"
2020-08-23 10:44:14 +02:00
bool doRelocation(std::vector<RelocationData *> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length);
2020-04-27 13:32:37 +02:00
bool CheckRunning() {
2020-08-23 10:44:14 +02:00
switch (ProcUIProcessMessages(true)) {
case PROCUI_STATUS_EXITING: {
return false;
}
case PROCUI_STATUS_RELEASE_FOREGROUND: {
ProcUIDrawDoneRelease();
break;
}
case PROCUI_STATUS_IN_FOREGROUND: {
break;
}
case PROCUI_STATUS_IN_BACKGROUND:
default:
break;
2020-04-27 13:32:37 +02:00
}
return true;
}
extern "C" void __init_wut();
extern "C" void __fini_wut();
2020-04-27 13:32:37 +02:00
extern "C" int _start(int argc, char **argv) {
doKernelSetup();
InitFunctionPointers();
doKernelSetup2();
2020-04-27 13:32:37 +02:00
__init_wut();
WHBLogUdpInit();
2020-04-27 13:32:37 +02:00
int res = 0;
uint32_t ApplicationMemoryEnd;
asm volatile("lis %0, __CODE_END@h; ori %0, %0, __CODE_END@l" : "=r" (ApplicationMemoryEnd));
ApplicationMemoryEnd = (ApplicationMemoryEnd + 0x100) & 0xFFFFFF00;
2020-08-23 10:44:14 +02:00
module_information_t *gModuleData = (module_information_t *) ApplicationMemoryEnd;
uint32_t moduleDataStartAddress = ((uint32_t) gModuleData + sizeof(module_information_t));
moduleDataStartAddress = (moduleDataStartAddress + 0x10000) & 0xFFFF0000;
2020-08-23 10:44:14 +02:00
ModuleData *moduleData = ModuleDataFactory::load("fs:/vol/external01/wiiu/payload.rpx", 0x00FFF000, 0x00FFF000 - ApplicationMemoryEnd, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH);
if (moduleData != NULL) {
DEBUG_FUNCTION_LINE("Loaded module data");
std::vector<RelocationData *> relocData = moduleData->getRelocationDataList();
2020-08-23 10:44:14 +02:00
if (!doRelocation(relocData, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH)) {
DEBUG_FUNCTION_LINE("relocations failed");
}
2020-08-23 10:44:14 +02:00
if (moduleData->getBSSAddr() != 0) {
DEBUG_FUNCTION_LINE("memset .bss %08X (%d)", moduleData->getBSSAddr(), moduleData->getBSSSize());
2020-08-23 10:44:14 +02:00
memset((void *) moduleData->getBSSAddr(), 0, moduleData->getBSSSize());
}
2020-08-23 10:44:14 +02:00
if (moduleData->getSBSSAddr() != 0) {
DEBUG_FUNCTION_LINE("memset .sbss %08X (%d)", moduleData->getSBSSAddr(), moduleData->getSBSSSize());
2020-08-23 10:44:14 +02:00
memset((void *) moduleData->getSBSSAddr(), 0, moduleData->getSBSSSize());
2020-04-27 13:32:37 +02:00
}
2020-08-23 10:44:14 +02:00
DCFlushRange((void *) 0x00800000, 0x00800000);
ICInvalidateRange((void *) 0x00800000, 0x00800000);
DEBUG_FUNCTION_LINE("New entrypoint: %08X", moduleData->getEntrypoint());
2020-08-23 10:44:14 +02:00
((int (*)(int, char **)) moduleData->getEntrypoint())(argc, argv);
delete moduleData;
2020-04-27 13:32:37 +02:00
} else {
DEBUG_FUNCTION_LINE("Failed to load module");
2020-04-27 13:32:37 +02:00
}
SYSLaunchMenu();
ProcUIInit(OSSavesDone_ReadyToRelease);
DEBUG_FUNCTION_LINE("In ProcUI loop");
2020-08-23 10:44:14 +02:00
while (CheckRunning()) {
2020-04-27 13:32:37 +02:00
// wait.
OSSleepTicks(OSMillisecondsToTicks(100));
}
ProcUIShutdown();
__fini_wut();
2020-04-27 13:32:37 +02:00
return 0;
}
2020-08-23 10:44:14 +02:00
bool doRelocation(std::vector<RelocationData *> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length) {
for (auto const &curReloc : relocData) {
RelocationData *cur = curReloc;
2020-04-27 13:32:37 +02:00
std::string functionName = cur->getName();
std::string rplName = cur->getImportRPLInformation()->getName();
int32_t isData = cur->getImportRPLInformation()->isData();
OSDynLoad_Module rplHandle = 0;
OSDynLoad_Acquire(rplName.c_str(), &rplHandle);
uint32_t functionAddress = 0;
2020-08-23 10:44:14 +02:00
OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void **) &functionAddress);
if (functionAddress == 0) {
2020-04-27 13:32:37 +02:00
return false;
}
2020-08-23 10:44:14 +02:00
if (!ElfUtils::elfLinkOne(cur->getType(), cur->getOffset(), cur->getAddend(), (uint32_t) cur->getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT)) {
DEBUG_FUNCTION_LINE("Relocation failed");
2020-04-27 13:32:37 +02:00
return false;
}
}
DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
return true;
}