From 781d76d5724534aaa3444d08ce539d252d821a39 Mon Sep 17 00:00:00 2001 From: Maschell Date: Fri, 19 Apr 2024 13:12:12 +0200 Subject: [PATCH 1/7] Allow logging in init hook --- source/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/main.cpp b/source/main.cpp index f70821d..3bec26a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -55,6 +55,10 @@ WUMS_INITIALIZE(args) { return; } +#ifdef DEBUG + initLogging(); +#endif + UpdateFunctionPointer(); ucSetupRequired = 0; @@ -73,6 +77,10 @@ WUMS_INITIALIZE(args) { OSFatal("homebrew_memorymapping: Failed to patch function"); } } + +#ifdef DEBUG + deinitLogging(); +#endif } WUMS_APPLICATION_STARTS() { From dcc2767b522d47923199671b75ecb07618e0b5eb Mon Sep 17 00:00:00 2001 From: Maschell Date: Fri, 19 Apr 2024 18:24:51 +0200 Subject: [PATCH 2/7] Make sure we can execute code on all three cores, check heaps on application end --- source/main.cpp | 11 ++- source/memory_mapping.cpp | 167 ++++++++++++++++++++++++++++++++++++++ source/memory_mapping.h | 2 + 3 files changed, 176 insertions(+), 4 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 3bec26a..9f37c6f 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -45,8 +45,6 @@ void UpdateFunctionPointer() { gMEMAllocFromDefaultHeapExForThreads = (void *(*) (uint32_t, int) ) * allocPtr; gMEMFreeToDefaultHeapForThreads = (void (*)(void *)) * freePtr; - - OSDynLoad_Release(coreinitModule); } WUMS_INITIALIZE(args) { @@ -86,6 +84,8 @@ WUMS_INITIALIZE(args) { WUMS_APPLICATION_STARTS() { OSReport("Running MemoryMappingModule " VERSION VERSION_EXTRA "\n"); + MemoryMapping_checkHeaps(); + // Now we can update the pointer with the "real" functions gMEMAllocFromDefaultHeapExForThreads = MEMAllocFromDefaultHeapEx; gMEMFreeToDefaultHeapForThreads = MEMFreeToDefaultHeap; @@ -95,11 +95,14 @@ WUMS_APPLICATION_STARTS() { #endif } + +WUMS_APPLICATION_ENDS() { + MemoryMapping_checkHeaps(); #ifdef DEBUG -WUMS_APPLICATION_REQUESTS_EXIT() { deinitLogging(); -} #endif +} + void MemoryMappingFree(void *ptr) { //DEBUG_FUNCTION_LINE("[%08X] free", ptr); diff --git a/source/memory_mapping.cpp b/source/memory_mapping.cpp index 820a28e..142b3f7 100644 --- a/source/memory_mapping.cpp +++ b/source/memory_mapping.cpp @@ -23,6 +23,149 @@ void runOnAllCores(CThread::Callback callback, void *callbackArg, int32_t iAttr } } +void KernelWriteU32(uint32_t addr, uint32_t value) { + ICInvalidateRange(&value, 4); + DCFlushRange(&value, 4); + + auto dst = (uint32_t) OSEffectiveToPhysical(addr); + auto src = (uint32_t) OSEffectiveToPhysical((uint32_t) &value); + + KernelCopyData(dst, src, 4); + + DCFlushRange((void *) addr, 4); + ICInvalidateRange((void *) addr, 4); +} + +void KernelWrite(uint32_t addr, const void *data, uint32_t length) { + // This is a hacky workaround, but currently it only works this way. ("data" is always on the stack, so maybe a problem with mapping values from the JIT area?) + // further testing required. + for (uint32_t i = 0; i < length; i += 4) { + KernelWriteU32(addr + i, *(uint32_t *) (((uint32_t) data) + i)); + } +} + + +/* +static void SCSetupIBAT4DBAT5() { + asm volatile("sync; eieio; isync"); + + // Give our and the kernel full execution rights. + // 00800000-01000000 => 30800000-31000000 (read/write, user/supervisor) + unsigned int ibat4u = 0x008000FF; + unsigned int ibat4l = 0x30800012; + asm volatile("mtspr 560, %0" :: "r"(ibat4u)); + asm volatile("mtspr 561, %0" :: "r"(ibat4l)); + + // Give our and the kernel full data access rights. + // 00800000-01000000 => 30800000-31000000 (read/write, user/supervisor) + unsigned int dbat5u = ibat4u; + unsigned int dbat5l = ibat4l; + asm volatile("mtspr 570, %0" :: "r"(dbat5u)); + asm volatile("mtspr 571, %0" :: "r"(dbat5l)); + + asm volatile("eieio; isync"); +} +*/ +const uint32_t sSCSetupIBAT4DBAT5Buffer[] = {0x7c0004ac, + 0x7c0006ac, + 0x4c00012c, + 0x3d400080, + 0x614a00ff, + 0x7d508ba6, + 0x3d203080, + 0x61290012, + 0x7d318ba6, + 0x7d5a8ba6, + 0x7d3b8ba6, + 0x7c0006ac, + 0x4c00012c, + 0x4e800020}; + +#define TARGET_ADDRESS_EXECUTABLE_MEM 0x017FF000 +#define SCSetupIBAT4DBAT5_ADDRESS TARGET_ADDRESS_EXECUTABLE_MEM + +const uint32_t sSC0x51Buffer[] = { + 0x7c7082a6, // mfspr r3, 528 + 0x60630003, // ori r3, r3, 0x03 + 0x7c7083a6, // mtspr 528, r3 + 0x7c7282a6, // mfspr r3, 530 + 0x60630003, // ori r3, r3, 0x03 + 0x7c7283a6, // mtspr 530, r3 + 0x7c0006ac, // eieio + 0x4c00012c, // isync + 0x3c600000 | (SCSetupIBAT4DBAT5_ADDRESS >> 16), // lis r3, SCSetupIBAT4DBAT5@h + 0x60630000 | (SCSetupIBAT4DBAT5_ADDRESS & 0xFFFF), // ori r3, r3, SCSetupIBAT4DBAT5@l + 0x7c6903a6, // mtctr r3 + 0x4e800420, // bctr +}; + +#define SC0x51Buffer_ADDRESS (SCSetupIBAT4DBAT5_ADDRESS + sizeof(sSCSetupIBAT4DBAT5Buffer)) +#define SC0x51Call_ADDRESS (SC0x51Buffer_ADDRESS + sizeof(sSC0x51Buffer)) + +const uint32_t sSC0x51CallBuffer[] = { + 0x38005100, //li %r0, 0x5100 + 0x44000002, // sc + 0x4e800020 //blr +}; + +void SetupIBAT4DBAT5OnAllCores() { + unsigned char backupBuffer[0x74]; + KernelWrite((uint32_t) backupBuffer, (void *) TARGET_ADDRESS_EXECUTABLE_MEM, sizeof(backupBuffer)); + + static_assert(sizeof(backupBuffer) >= (sizeof(sSC0x51Buffer) + sizeof(sSCSetupIBAT4DBAT5Buffer) + sizeof(sSC0x51CallBuffer)), "Not enough memory in backup buffer"); + static_assert(SCSetupIBAT4DBAT5_ADDRESS >= TARGET_ADDRESS_EXECUTABLE_MEM && SCSetupIBAT4DBAT5_ADDRESS < (TARGET_ADDRESS_EXECUTABLE_MEM + sizeof(backupBuffer)), "buffer in wrong memory region"); + static_assert(SC0x51Buffer_ADDRESS >= TARGET_ADDRESS_EXECUTABLE_MEM && SC0x51Buffer_ADDRESS < (TARGET_ADDRESS_EXECUTABLE_MEM + sizeof(backupBuffer)), "buffer in wrong memory region"); + static_assert(SC0x51Call_ADDRESS >= TARGET_ADDRESS_EXECUTABLE_MEM && SC0x51Call_ADDRESS < (TARGET_ADDRESS_EXECUTABLE_MEM + sizeof(backupBuffer)), "buffer in wrong memory region"); + static_assert(SCSetupIBAT4DBAT5_ADDRESS != SC0x51Buffer_ADDRESS && SCSetupIBAT4DBAT5_ADDRESS != SC0x51Call_ADDRESS && SC0x51Buffer_ADDRESS != SC0x51Call_ADDRESS, "buffer are not different"); + + // We need copy the functions to a memory region which is executable on all 3 cores + KernelWrite(SCSetupIBAT4DBAT5_ADDRESS, sSCSetupIBAT4DBAT5Buffer, sizeof(sSCSetupIBAT4DBAT5Buffer)); // Set IBAT5 and DBAT5 to map the memory region + KernelWrite(SC0x51Buffer_ADDRESS, sSC0x51Buffer, sizeof(sSC0x51Buffer)); // Implementation of 0x51 syscall + KernelWrite(SC0x51Call_ADDRESS, sSC0x51CallBuffer, sizeof(sSC0x51CallBuffer)); // Call of 0x51 syscall + + /* set our setup syscall to an unused position */ + KernelPatchSyscall(0x51, SCSetupIBAT4DBAT5_ADDRESS); + + // We want to run this on all 3 cores. + { + int32_t aff[] = {CThread::eAttributeAffCore2, CThread::eAttributeAffCore1, CThread::eAttributeAffCore0}; + + int iStackSize = 0x200; + + //! allocate the thread and stack on the default Cafe OS heap + auto *pThread = (OSThread *) gMEMAllocFromDefaultHeapExForThreads(sizeof(OSThread), 0x10); + auto *pThreadStack = (uint8_t *) gMEMAllocFromDefaultHeapExForThreads(iStackSize, 0x20); + //! create the thread + if (pThread && pThreadStack) { + for (int i : aff) { + *pThread = {}; + memset(pThreadStack, 0, iStackSize); + OSCreateThread(pThread, reinterpret_cast(SC0x51Call_ADDRESS), 0, nullptr, (void *) (pThreadStack + iStackSize), iStackSize, 16, (OSThreadAttributes) i); + OSResumeThread(pThread); + + while (OSIsThreadSuspended(pThread)) { + OSResumeThread(pThread); + } + OSJoinThread(pThread, nullptr); + } + } + + //! free the thread stack buffer + if (pThreadStack) { + memset(pThreadStack, 0, iStackSize); + gMEMFreeToDefaultHeapForThreads(pThreadStack); + } + if (pThread) { + memset(pThread, 0, sizeof(OSThread)); + gMEMFreeToDefaultHeapForThreads(pThread); + } + } + + /* repair data */ + KernelWrite(TARGET_ADDRESS_EXECUTABLE_MEM, backupBuffer, sizeof(backupBuffer)); + DCFlushRange((void *) TARGET_ADDRESS_EXECUTABLE_MEM, sizeof(backupBuffer)); +} + void writeKernelNOPs(CThread *thread, void *arg) { DEBUG_FUNCTION_LINE_VERBOSE("Writing kernel NOPs on core %d", OSGetThreadAffinity(OSGetCurrentThread()) / 2); @@ -339,6 +482,11 @@ void MemoryMapping_memoryMappingForRegions(const memory_mapping_t *memory_mappin } void MemoryMapping_setupMemoryMapping() { + /* + * We need to make sure that with have full access to the 0x0080000-0x01000000 region on all 3 cores. + */ + SetupIBAT4DBAT5OnAllCores(); + // Override all writes to SR8 with nops. // Override some memory region checks inside the kernel runOnAllCores(writeKernelNOPs, nullptr); @@ -443,6 +591,25 @@ void *MemoryMapping_allocEx(uint32_t size, int32_t align, bool videoOnly) { return res; } +extern "C" bool MEMCheckExpHeap(MEMHeapHandle heap, bool logProblems); + +void MemoryMapping_checkHeaps() { + OSLockMutex(&allocMutex); + for (int32_t i = 0; /* waiting for a break */; i++) { + if (mem_mapping[i].physical_addresses == nullptr) { + break; + } + auto heapHandle = (MEMHeapHandle) mem_mapping[i].effective_start_address; + if (!MEMCheckExpHeap(heapHandle, true)) { + DEBUG_FUNCTION_LINE_ERR("MemoryMapping heap %08X (index %d) is corrupted.", heapHandle, i); +#ifdef DEBUG + OSFatal("MemoryMappingModule: Heap is corrupted"); +#endif + } + } + OSUnlockMutex(&allocMutex); +} + void *MemoryMapping_alloc(uint32_t size, int32_t align) { return MemoryMapping_allocEx(size, align, false); } diff --git a/source/memory_mapping.h b/source/memory_mapping.h index fd1d38c..93df258 100644 --- a/source/memory_mapping.h +++ b/source/memory_mapping.h @@ -201,6 +201,8 @@ void MemoryMapping_readTestValuesFromMemory(); void MemoryMapping_searchEmptyMemoryRegions(); +void MemoryMapping_checkHeaps(); + void *MemoryMapping_alloc(uint32_t size, int32_t align); void *MemoryMapping_allocVideoMemory(uint32_t size, int32_t align); From 451df2e5b507aac4348da6ad52eca917edd07445 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 04:11:25 +0000 Subject: [PATCH 3/7] Bump wiiu-env/devkitppc from 20230621 to 20231112 Bumps wiiu-env/devkitppc from 20230621 to 20231112. --- updated-dependencies: - dependency-name: wiiu-env/devkitppc dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5d746a6..a07d024 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/wiiu-env/devkitppc:20230621 +FROM ghcr.io/wiiu-env/devkitppc:20231112 COPY --from=ghcr.io/wiiu-env/libkernel:20230621 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO From 408e5d05086d6bbb5190aad29e410cec75ff6094 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 04:33:04 +0000 Subject: [PATCH 4/7] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- .github/workflows/pr.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed565aa..e5c15ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: clang-format: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: clang-format run: | docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-22.04 needs: clang-format steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: create version.h run: | git_hash=$(git rev-parse --short "$GITHUB_SHA") diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 90ac4e9..c82c7e4 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,7 +6,7 @@ jobs: clang-format: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: clang-format run: | docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-22.04 needs: clang-format steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: build binary with logging run: | docker build . -t builder @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-22.04 needs: clang-format steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: create version.h run: | git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}") From cd3c9aa95cad51671312fed78c2c8c18920f37f5 Mon Sep 17 00:00:00 2001 From: Maschell Date: Thu, 25 Apr 2024 11:23:19 +0200 Subject: [PATCH 5/7] Bump version to 0.2.6 --- source/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/main.cpp b/source/main.cpp index 9f37c6f..648f4cb 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -10,7 +10,7 @@ #include "logger.h" #endif -#define VERSION "v0.2.5" +#define VERSION "v0.2.6" WUMS_MODULE_EXPORT_NAME("homebrew_memorymapping"); WUMS_MODULE_SKIP_INIT_FINI(); From bf281bc236d6d0b3c820264082433ebf935732fd Mon Sep 17 00:00:00 2001 From: Maschell Date: Thu, 25 Apr 2024 11:23:41 +0200 Subject: [PATCH 6/7] Update Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index a07d024..20da8e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM ghcr.io/wiiu-env/devkitppc:20231112 +FROM ghcr.io/wiiu-env/devkitppc:20240423 COPY --from=ghcr.io/wiiu-env/libkernel:20230621 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO -COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20230719 /artifacts $DEVKITPRO +COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20240424 /artifacts $DEVKITPRO WORKDIR project From d40f4939a97fb5ec6be3556660c707a93aa6dca8 Mon Sep 17 00:00:00 2001 From: Maschell Date: Thu, 25 Apr 2024 11:28:57 +0200 Subject: [PATCH 7/7] Fix compiling with latest wut version --- source/memory_mapping.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/memory_mapping.cpp b/source/memory_mapping.cpp index 142b3f7..7d257da 100644 --- a/source/memory_mapping.cpp +++ b/source/memory_mapping.cpp @@ -591,8 +591,6 @@ void *MemoryMapping_allocEx(uint32_t size, int32_t align, bool videoOnly) { return res; } -extern "C" bool MEMCheckExpHeap(MEMHeapHandle heap, bool logProblems); - void MemoryMapping_checkHeaps() { OSLockMutex(&allocMutex); for (int32_t i = 0; /* waiting for a break */; i++) { @@ -600,7 +598,7 @@ void MemoryMapping_checkHeaps() { break; } auto heapHandle = (MEMHeapHandle) mem_mapping[i].effective_start_address; - if (!MEMCheckExpHeap(heapHandle, true)) { + if (!MEMCheckExpHeap(heapHandle, MEM_EXP_HEAP_CHECK_FLAGS_LOG_ERRORS)) { DEBUG_FUNCTION_LINE_ERR("MemoryMapping heap %08X (index %d) is corrupted.", heapHandle, i); #ifdef DEBUG OSFatal("MemoryMappingModule: Heap is corrupted");