recovery_menu/ios_kernel/source/main.c
GaryOderNichts 259baac34c Fixes for building on latest devkitARM
GCC 14.1 seems to generate larger binaries
2024-07-03 19:02:29 +02:00

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;
}