mirror of
https://github.com/GaryOderNichts/recovery_menu.git
synced 2025-06-19 03:05:32 -04:00
109 lines
3.5 KiB
C
109 lines
3.5 KiB
C
#include "imports.h"
|
|
#include "thread.h"
|
|
#include "lolserial.h"
|
|
#include "bsp.h"
|
|
#include "../../ios_mcp/ios_mcp_syms.h"
|
|
|
|
extern char __kernel_bss_start;
|
|
extern char __kernel_bss_end;
|
|
|
|
extern char svcAB_handler;
|
|
|
|
extern uint32_t domainAccessPermissions[];
|
|
|
|
int kernel_syscall_0x81(int type, uint32_t address, uint32_t value)
|
|
{
|
|
int res = 0;
|
|
int level = disable_interrupts();
|
|
set_domain_register(domainAccessPermissions[0]); // 0 = KERNEL
|
|
|
|
if (type == 0) { // kernRead32
|
|
res = *(volatile uint32_t*) address;
|
|
} else if (type == 1) { // kernWrite32
|
|
*(volatile uint32_t*) address = value;
|
|
}
|
|
|
|
set_domain_register(domainAccessPermissions[currentThreadContext->pid]);
|
|
enable_interrupts(level);
|
|
|
|
return res;
|
|
}
|
|
|
|
int _main(void* arg)
|
|
{
|
|
lolserial_printf("Hello world from recovery_menu. Running from '%s'.\n", arg);
|
|
|
|
int level = disable_interrupts();
|
|
uint32_t control_register = disable_mmu();
|
|
|
|
// clear all bss
|
|
memset(&__kernel_bss_start, 0, &__kernel_bss_end - &__kernel_bss_start);
|
|
memset((void*) (__mcp_bss_start - 0x05074000 + 0x08234000), 0, __mcp_bss_end - __mcp_bss_start);
|
|
|
|
// map the mcp sections
|
|
ios_map_shared_info_t map_info;
|
|
map_info.paddr = 0x050bd000 - 0x05000000 + 0x081c0000;
|
|
map_info.vaddr = 0x050bd000;
|
|
map_info.size = 0x3000;
|
|
map_info.domain = 1; // MCP
|
|
map_info.type = 3;
|
|
map_info.cached = 0xffffffff;
|
|
_iosMapSharedUserExecution(&map_info);
|
|
|
|
map_info.paddr = 0x05116000 - 0x05100000 + 0x13d80000;
|
|
map_info.vaddr = 0x05116000;
|
|
// According to <https://wiiubrew.org/wiki/Memory_map> we can map up to 0x2A000 bytes here
|
|
// Since we don't configure AHMN though, we only have up to 0x16000 bytes left on the current page
|
|
map_info.size = 0x16000;
|
|
map_info.domain = 1; // MCP
|
|
map_info.type = 3;
|
|
map_info.cached = 0xffffffff;
|
|
_iosMapSharedUserExecution(&map_info);
|
|
|
|
// redirect __sys_write0 to lolserial
|
|
*(volatile uint32_t*) 0x0812dd68 = ARM_B(0x0812dd68, (uint32_t) &svcAB_handler);
|
|
|
|
// add mcp ioctl hook to start mcp thread
|
|
*(volatile uint32_t*) (0x05025242 - 0x05000000 + 0x081c0000) = THUMB_BL(0x05025242, _MCP_ioctl100_patch);
|
|
|
|
// replace custom kernel syscall
|
|
*(volatile uint32_t*) 0x0812cd2c = ARM_B(0x0812cd2c, kernel_syscall_0x81);
|
|
|
|
// patch IOS_ReadOTP to allow read from all processes
|
|
*(volatile uint32_t*) 0x0812037c = 0xe15c000c; // cmp r12, r12
|
|
|
|
// patch MCP_SetSysProdSettings debug mode check
|
|
*(volatile uint32_t*) (0x05024648 - 0x05000000 + 0x081c0000) = 0x20002000; // mov r0, #0; mov r0, #0
|
|
|
|
// nop out odm log to not spam logs when stopping drive
|
|
*(volatile uint32_t*) 0x1073880c = 0xe12fff1e; // bx lr
|
|
|
|
restore_mmu(control_register);
|
|
|
|
// invalidate all cache
|
|
invalidate_dcache(NULL, 0x4001);
|
|
invalidate_icache();
|
|
|
|
enable_interrupts(level);
|
|
|
|
// set LED to purple-off blinking
|
|
uint8_t ledMask = 0x3c; // NOTIF_LED_RED | NOTIF_LED_RED_BLINKING | NOTIF_LED_BLUE | NOTIF_LED_BLUE_BLINKING
|
|
bspWrite("SMC", 0, "NotificationLED", 1, &ledMask);
|
|
|
|
// give the current thread full access to MCP for starting the thread
|
|
setClientCapabilities(currentThreadContext->pid, 0xd, 0xffffffffffffffffllu);
|
|
|
|
// start mcp thread
|
|
int mcpHandle = IOS_Open("/dev/mcp", 0);
|
|
if (mcpHandle > 0) {
|
|
lolserial_printf("Starting MCP thread...\n");
|
|
IOS_Ioctl(mcpHandle, 100, NULL, 0, NULL, 0);
|
|
|
|
IOS_Close(mcpHandle);
|
|
} else {
|
|
lolserial_printf("Cannot open MCP: %x\n", mcpHandle);
|
|
}
|
|
|
|
return 0;
|
|
}
|