Make it compatible with the EnvironmentLoader

This commit is contained in:
Maschell 2021-12-28 18:38:22 +01:00
parent 8fa1485942
commit f2abd5945a
6 changed files with 85 additions and 109 deletions

View File

@ -18,7 +18,7 @@ WUMS_ROOT := $(DEVKITPRO)/wums
# DATA is a list of directories containing data files # DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files # INCLUDES is a list of directories containing header files
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
TARGET := payload TARGET := 10_wums_loader
BUILD := build BUILD := build
SOURCES := source \ SOURCES := source \
source/elfio\ source/elfio\
@ -39,7 +39,7 @@ CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
CXXFLAGS := $(CFLAGS) -std=c++20 CXXFLAGS := $(CFLAGS) -std=c++20
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) LDFLAGS = -g $(ARCH) $(RPXSPECS) --entry=_start -Wl,-Map,$(notdir $*.map)
LIBS := -lwut -lz LIBS := -lwut -lz

View File

@ -1,14 +1,12 @@
# Setup payload # Wii U Module System Loader
This is a payload that should be run with [CustomRPXLoader](https://github.com/wiiu-env/CustomRPXLoader). This is a payload that should be run with [EnvironmentLoader](https://github.com/wiiu-env/EnvironmentLoader).
## Usage ## Usage
Put the `payload.rpx` in the `sd:/wiiu/` folder of your sd card and use the `CustomRPXLoader` to run this setup payload. Put the `10_wums_loader.rpx` in the `fs:/vol/external01/wiiu/environments/[ENVIRONMENT]/modules/setup` folder of your sd card and use the `EnvironmentLoader` to run this setup payload.
Put modules (in form of `.wms` files) that should be used a main()-hook into `sd:/wiiu/modules/` and one time modules into `sd:/wiiu/modules/setup`. Put modules (in form of `.wms` files) that should be used a main()-hook into `fs:/vol/external01/wiiu/environments/[ENVIRONMENT]/modules/`.
- Make sure not to call `exit` in the modules (by using the WiiUModuleSystem)
- The one time setups will be run in the order of their ordered filenames.
The area between `0x00800000` and whereever this setup is loaded, will be used. The area between `0x00800000` and whereever this loader is loaded, will be used.
## Building ## Building
Make you to have [wut](https://github.com/devkitPro/wut/) and [WiiUModuleSystem](https://github.com/wiiu-env/WiiUModuleSystem) installed and use the following command for build: Make you to have [wut](https://github.com/devkitPro/wut/) and [WiiUModuleSystem](https://github.com/wiiu-env/WiiUModuleSystem) installed and use the following command for build:
@ -22,13 +20,13 @@ It's possible to use a docker image for building. This way you don't need anythi
``` ```
# Build docker image (only needed once) # Build docker image (only needed once)
docker build . -t setuppayload-builder docker build . -t wumsloader-builder
# make # make
docker run -it --rm -v ${PWD}:/project setuppayload-builder make docker run -it --rm -v ${PWD}:/project wumsloader-builder make
# make clean # make clean
docker run -it --rm -v ${PWD}:/project setuppayload-builder make clean docker run -it --rm -v ${PWD}:/project wumsloader-builder make clean
``` ```

36
source/crt.c Normal file
View File

@ -0,0 +1,36 @@
void __init_wut_malloc();
void __init_wut_newlib();
void __init_wut_stdcpp();
void __init_wut_devoptab();
void __attribute__((weak)) __init_wut_socket();
void __fini_wut_malloc();
void __fini_wut_newlib();
void __fini_wut_stdcpp();
void __fini_wut_devoptab();
void __attribute__((weak)) __fini_wut_socket();
void __attribute__((weak))
__init_wut_() {
__init_wut_malloc();
__init_wut_newlib();
__init_wut_stdcpp();
__init_wut_devoptab();
if (&__init_wut_socket) __init_wut_socket();
}
void __attribute__((weak))
__fini_wut_() {
__fini_wut_devoptab();
__fini_wut_stdcpp();
__fini_wut_newlib();
__fini_wut_malloc();
}

29
source/crt0.s Normal file
View File

@ -0,0 +1,29 @@
.extern main
.extern exit
.extern __init_wut_
.extern __fini_wut_
.global _start
_start:
stwu 1, -0x28(1)
mflr 0
stw 0, 0x2C(1)
stw 31, 0x24(1)
or 31, 1, 1
stw 3, 0x18(31)
stw 4, 0x1C(31)
bl __init_wut_
lwz 4, 0x1C(31)
lwz 3, 0x18(31)
bl main
or 9, 3, 3
stw 9, 0x8(31)
bl __fini_wut_
lwz 9, 0x8(31)
or 3, 9, 9
addi 11, 31, 0x28
lwz 0, 0x4(11)
mtlr 0
lwz 31, -0x4(11)
or 1, 11, 11
blr

View File

@ -1,17 +1,11 @@
#include <cstring> #include <cstring>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <proc_ui/procui.h>
#include <sysapp/launch.h> #include <sysapp/launch.h>
#include <coreinit/foreground.h>
#include <coreinit/cache.h>
#include <nn/act/client_cpp.h> #include <nn/act/client_cpp.h>
#include <coreinit/dynload.h>
#include <whb/log_udp.h> #include <whb/log_udp.h>
#include <whb/log_cafe.h> #include <whb/log_cafe.h>
#include <whb/log_module.h> #include <whb/log_module.h>
#include <vector>
#include <memory>
#include "fs/DirList.h" #include "fs/DirList.h"
#include "module/ModuleDataPersistence.h" #include "module/ModuleDataPersistence.h"
@ -20,106 +14,33 @@
#include "kernel.h" #include "kernel.h"
#include "globals.h" #include "globals.h"
bool CheckRunning() {
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;
}
return true;
}
extern "C" uint32_t textStart(); extern "C" uint32_t textStart();
extern "C" void _SYSLaunchMenuWithCheckingAccount(nn::act::SlotNo slot);
bool doRelocation(std::vector<std::shared_ptr<RelocationData>> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length) {
for (auto const &curReloc: relocData) {
std::string functionName = curReloc->getName();
std::string rplName = curReloc->getImportRPLInformation()->getName();
int32_t isData = curReloc->getImportRPLInformation()->isData();
OSDynLoad_Module rplHandle = nullptr;
if (OSDynLoad_IsModuleLoaded(rplName.c_str(), &rplHandle) != OS_DYNLOAD_OK) {
// only acquire if not already loaded.
OSDynLoad_Acquire(rplName.c_str(), &rplHandle);
}
uint32_t functionAddress = 0;
OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void **) &functionAddress);
if (functionAddress == 0) {
return false;
}
if (!ElfUtils::elfLinkOne(curReloc->getType(), curReloc->getOffset(), curReloc->getAddend(), (uint32_t) curReloc->getDestination(), functionAddress, tramp_data, tramp_length,
RELOC_TYPE_IMPORT)) {
DEBUG_FUNCTION_LINE("Relocation failed\n");
return false;
}
}
DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
return true;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
if (!WHBLogModuleInit()) { if (!WHBLogModuleInit()) {
WHBLogCafeInit(); WHBLogCafeInit();
WHBLogUdpInit(); WHBLogUdpInit();
} }
// 0x100 because before the .text section is a .init section // We subtract 0x100 to be safe.
// Currently the size of the .init is ~ 0x24 bytes. We substract 0x100 to be safe. uint32_t textSectionStart = textStart() - 0x100;
uint32_t textSectionStart = textStart() - 0x1000;
DirList setupModules("fs:/vol/external01/wiiu/modules/setup", ".rpx", DirList::Files, 1);
setupModules.SortList();
for (int i = 0; i < setupModules.GetFilecount(); i++) {
uint32_t destination_address = ((uint32_t) gModuleData + (sizeof(module_information_t) + 0x0000FFFF)) & 0xFFFF0000;
memset((void *) gModuleData, 0, sizeof(module_information_t));
DEBUG_FUNCTION_LINE("Trying to run %s", setupModules.GetFilepath(i));
auto moduleData = ModuleDataFactory::load(setupModules.GetFilepath(i), &destination_address, textSectionStart - destination_address, gModuleData->trampolines,
DYN_LINK_TRAMPOLIN_LIST_LENGTH);
if (!moduleData) {
DEBUG_FUNCTION_LINE("Failed to load %s", setupModules.GetFilepath(i));
continue;
}
DEBUG_FUNCTION_LINE("Loaded module data");
auto relocData = moduleData.value()->getRelocationDataList();
if (!doRelocation(relocData, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH)) {
DEBUG_FUNCTION_LINE("relocations failed\n");
}
DCFlushRange((void *) moduleData.value()->getStartAddress(), moduleData.value()->getEndAddress() - moduleData.value()->getStartAddress());
ICInvalidateRange((void *) moduleData.value()->getStartAddress(), moduleData.value()->getEndAddress() - moduleData.value()->getStartAddress());
DEBUG_FUNCTION_LINE("Calling entrypoint @%08X", moduleData.value()->getEntrypoint());
((int (*)(int, char **)) moduleData.value()->getEntrypoint())(argc, argv);
DEBUG_FUNCTION_LINE("Back from module");
}
memset((void *) gModuleData, 0, sizeof(module_information_t)); memset((void *) gModuleData, 0, sizeof(module_information_t));
gModuleData->version = MODULE_INFORMATION_VERSION; gModuleData->version = MODULE_INFORMATION_VERSION;
DirList modules("fs:/vol/external01/wiiu/modules", ".wms", DirList::Files, 1); std::string basePath = "fs:/vol/external01/wiiu";
if (argc >= 1) {
basePath = argv[0];
}
DirList modules(basePath + "/modules", ".wms", DirList::Files, 1);
modules.SortList(); modules.SortList();
uint32_t destination_address = ((uint32_t) gModuleData + (sizeof(module_information_t) + 0x0000FFFF)) & 0xFFFF0000; uint32_t destination_address = ((uint32_t) gModuleData + (sizeof(module_information_t) + 0x0000FFFF)) & 0xFFFF0000;
for (int i = 0; i < modules.GetFilecount(); i++) { for (int i = 0; i < modules.GetFilecount(); i++) {
DEBUG_FUNCTION_LINE("Loading module %s", modules.GetFilepath(i)); DEBUG_FUNCTION_LINE("Loading module %s", modules.GetFilepath(i));
auto moduleData = ModuleDataFactory::load(modules.GetFilepath(i), &destination_address, MEMORY_REGION_USABLE_END - destination_address, gModuleData->trampolines, auto moduleData = ModuleDataFactory::load(modules.GetFilepath(i), &destination_address, textSectionStart - destination_address, gModuleData->trampolines,
DYN_LINK_TRAMPOLIN_LIST_LENGTH); DYN_LINK_TRAMPOLIN_LIST_LENGTH);
if (moduleData) { if (moduleData) {
DEBUG_FUNCTION_LINE("Successfully loaded %s", modules.GetFilepath(i)); DEBUG_FUNCTION_LINE("Successfully loaded %s", modules.GetFilepath(i));
ModuleDataPersistence::saveModuleData(gModuleData, moduleData.value()); ModuleDataPersistence::saveModuleData(gModuleData, moduleData.value());
@ -132,8 +53,6 @@ int main(int argc, char **argv) {
WHBLogUdpDeinit(); WHBLogUdpDeinit();
ProcUIInit(OSSavesDone_ReadyToRelease);
nn::act::Initialize(); nn::act::Initialize();
nn::act::SlotNo slot = nn::act::GetSlotNo(); nn::act::SlotNo slot = nn::act::GetSlotNo();
nn::act::SlotNo defaultSlot = nn::act::GetDefaultAccount(); nn::act::SlotNo defaultSlot = nn::act::GetDefaultAccount();
@ -144,11 +63,5 @@ int main(int argc, char **argv) {
} else { //show mii select } else { //show mii select
_SYSLaunchMenuWithCheckingAccount(slot); _SYSLaunchMenuWithCheckingAccount(slot);
} }
while (CheckRunning()) {
// wait.
OSSleepTicks(OSMillisecondsToTicks(100));
}
ProcUIShutdown();
return 0; return 0;
} }

View File

@ -1,4 +1,4 @@
.section ".text" .section ".crt0"
.global textStart .global textStart
textStart: textStart:
mflr 4; mflr 4;