mirror of
https://github.com/wiiu-env/WUMSLoader.git
synced 2024-11-27 01:54:16 +01:00
Make it compatible with the EnvironmentLoader
This commit is contained in:
parent
8fa1485942
commit
f2abd5945a
4
Makefile
4
Makefile
@ -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
|
||||||
|
|
||||||
|
18
README.md
18
README.md
@ -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
36
source/crt.c
Normal 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
29
source/crt0.s
Normal 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
|
105
source/main.cpp
105
source/main.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.section ".text"
|
.section ".crt0"
|
||||||
.global textStart
|
.global textStart
|
||||||
textStart:
|
textStart:
|
||||||
mflr 4;
|
mflr 4;
|
||||||
|
Loading…
Reference in New Issue
Block a user