209 lines
7.4 KiB
C
209 lines
7.4 KiB
C
#include "common/os_defs.h"
|
|
#include "common/kernel_defs.h"
|
|
#include "common/common.h"
|
|
#include "dynamic_libs/os_functions.h"
|
|
#include "utils/utils.h"
|
|
#include "syscalls.h"
|
|
|
|
extern void my_PrepareTitle_hook(void);
|
|
|
|
static unsigned int origPrepareTitleInstr __attribute__((section(".data"))) = 0;
|
|
|
|
static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)
|
|
{
|
|
/*
|
|
* Setup a DBAT access for our 0xC0800000 area and our 0xBC000000 area which hold our variables like GAME_LAUNCHED and our BSS/rodata section
|
|
*/
|
|
register int dbatu0, dbatl0, dbatu1, dbatl1;
|
|
// save the original DBAT value
|
|
asm volatile("mfdbatu %0, 0" : "=r" (dbatu0));
|
|
asm volatile("mfdbatl %0, 0" : "=r" (dbatl0));
|
|
asm volatile("mfdbatu %0, 1" : "=r" (dbatu1));
|
|
asm volatile("mfdbatl %0, 1" : "=r" (dbatl1));
|
|
|
|
// write our own DBATs into the array
|
|
if( ((addr & 0xFFF00000) == 0xFFF00000) || ((src & 0xFFF00000) == 0xFFF00000) )
|
|
{
|
|
// setup kernel code access
|
|
unsigned int dbatu = 0;
|
|
unsigned int dbatl = 0;
|
|
|
|
if((src & 0xFFF00000) == 0xFFF00000) {
|
|
dbatu = (src & 0xFFF00000) | 0x02;
|
|
dbatl = (src & 0xFFF00000) | 0x32;
|
|
}
|
|
else {
|
|
dbatu = (addr & 0xFFF00000) | 0x02;
|
|
dbatl = (addr & 0xFFF00000) | 0x32;
|
|
}
|
|
|
|
if( ((addr & 0xFFF00000) != (dbatu0 & 0xFFF00000)) && ((src & 0xFFF00000) != (dbatu0 & 0xFFF00000)) )
|
|
{
|
|
asm volatile("mtdbatu 0, %0" : : "r" (dbatu));
|
|
asm volatile("mtdbatl 0, %0" : : "r" (dbatl));
|
|
}
|
|
else
|
|
{
|
|
asm volatile("mtdbatu 1, %0" : : "r" (dbatu));
|
|
asm volatile("mtdbatl 1, %0" : : "r" (dbatl));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
asm volatile("mtdbatu 0, %0" : : "r" (0xC0001FFF));
|
|
asm volatile("mtdbatl 0, %0" : : "r" (0x30000012));
|
|
asm volatile("mtdbatu 1, %0" : : "r" (0xB0801FFF));
|
|
asm volatile("mtdbatl 1, %0" : : "r" (0x20800012));
|
|
}
|
|
asm volatile("eieio; isync");
|
|
|
|
|
|
unsigned char *src_p = (unsigned char*)src;
|
|
unsigned char *dst_p = (unsigned char*)addr;
|
|
|
|
unsigned int i;
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
dst_p[i] = src_p[i];
|
|
}
|
|
|
|
/*
|
|
* Restore original DBAT value
|
|
*/
|
|
asm volatile("mtdbatu 0, %0" : : "r" (dbatu0));
|
|
asm volatile("mtdbatl 0, %0" : : "r" (dbatl0));
|
|
asm volatile("mtdbatu 1, %0" : : "r" (dbatu1));
|
|
asm volatile("mtdbatl 1, %0" : : "r" (dbatl1));
|
|
asm volatile("eieio; isync");
|
|
}
|
|
|
|
static void KernelReadDBATs(bat_table_t * table)
|
|
{
|
|
u32 i = 0;
|
|
|
|
asm volatile("eieio; isync");
|
|
|
|
asm volatile("mfspr %0, 536" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 537" : "=r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mfspr %0, 538" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 539" : "=r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mfspr %0, 540" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 541" : "=r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mfspr %0, 542" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 543" : "=r" (table->bat[i].l));
|
|
i++;
|
|
|
|
asm volatile("mfspr %0, 568" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 569" : "=r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mfspr %0, 570" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 571" : "=r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mfspr %0, 572" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 573" : "=r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mfspr %0, 574" : "=r" (table->bat[i].h));
|
|
asm volatile("mfspr %0, 575" : "=r" (table->bat[i].l));
|
|
}
|
|
|
|
static void KernelWriteDBATs(bat_table_t * table)
|
|
{
|
|
u32 i = 0;
|
|
|
|
asm volatile("eieio; isync");
|
|
|
|
asm volatile("mtspr 536, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 537, %0" : : "r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mtspr 538, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 539, %0" : : "r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mtspr 540, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 541, %0" : : "r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mtspr 542, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 543, %0" : : "r" (table->bat[i].l));
|
|
i++;
|
|
|
|
asm volatile("mtspr 568, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 569, %0" : : "r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mtspr 570, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 571, %0" : : "r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mtspr 572, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 573, %0" : : "r" (table->bat[i].l));
|
|
i++;
|
|
asm volatile("mtspr 574, %0" : : "r" (table->bat[i].h));
|
|
asm volatile("mtspr 575, %0" : : "r" (table->bat[i].l));
|
|
|
|
asm volatile("eieio; isync");
|
|
}
|
|
|
|
/* Write a 32-bit word with kernel permissions */
|
|
static void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)
|
|
{
|
|
asm volatile (
|
|
"li 3,1\n"
|
|
"li 4,0\n"
|
|
"mr 5,%1\n"
|
|
"li 6,0\n"
|
|
"li 7,0\n"
|
|
"lis 8,1\n"
|
|
"mr 9,%0\n"
|
|
"mr %1,1\n"
|
|
"li 0,0x3500\n"
|
|
"sc\n"
|
|
"nop\n"
|
|
"mr 1,%1\n"
|
|
:
|
|
: "r"(addr), "r"(value)
|
|
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
|
|
"11", "12"
|
|
);
|
|
}
|
|
|
|
void KernelSetupSyscalls(void)
|
|
{
|
|
//! assign 1 so that this variable gets into the retained .data section
|
|
static uint8_t ucSyscallsSetupRequired = 1;
|
|
if(!ucSyscallsSetupRequired)
|
|
return;
|
|
|
|
ucSyscallsSetupRequired = 0;
|
|
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x36 * 4)), (unsigned int)KernelReadDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x36 * 4)), (unsigned int)KernelReadDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x36 * 4)), (unsigned int)KernelReadDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x36 * 4)), (unsigned int)KernelReadDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x36 * 4)), (unsigned int)KernelReadDBATs);
|
|
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);
|
|
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int)KernelCopyData);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int)KernelCopyData);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int)KernelCopyData);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int)KernelCopyData);
|
|
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int)KernelCopyData);
|
|
|
|
//! write our hook to the
|
|
u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003;
|
|
|
|
SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4);
|
|
SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&addr_my_PrepareTitle_hook, 4);
|
|
}
|
|
|
|
|
|
void KernelRestoreInstructions(void)
|
|
{
|
|
if(origPrepareTitleInstr != 0)
|
|
SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&origPrepareTitleInstr, 4);
|
|
}
|