HBLInstallerWrapper/source/kernel_patches.s

212 lines
4.9 KiB
ArmAsm

#define BAT_SETUP_HOOK_ADDR 0xFFF1D624
# not all of those NOP address are required for every firmware
# mainly these should stop the kernel from removing our IBAT4 and DBAT5
#define BAT_SET_NOP_ADDR_1 0xFFF06B6C
#define BAT_SET_NOP_ADDR_2 0xFFF06BF8
#define BAT_SET_NOP_ADDR_3 0xFFF003C8
#define BAT_SET_NOP_ADDR_4 0xFFF003CC
#define BAT_SET_NOP_ADDR_5 0xFFF1D70C
#define BAT_SET_NOP_ADDR_6 0xFFF1D728
#define BAT_SET_NOP_ADDR_7 0xFFF1D82C
#define BAT_SET_NOP_ADDR_8 0xFFEE11C4
#define BAT_SET_NOP_ADDR_9 0xFFEE11C8
#define BAT_SETUP_HOOK_ENTRY 0x00800000
#define BAT4U_VAL 0x008000FF
#define BAT4L_VAL 0x30800012
#define SET_R4_TO_ADDR(addr) \
lis r3, addr@h ; \
ori r3, r3, addr@l ; \
stw r4, 0(r3) ; \
dcbf 0, r3 ; \
icbi 0, r3 ;
.globl Syscall_0x36
Syscall_0x36:
li r0, 0x3600
sc
blr
.global SCKernelCopyData
SCKernelCopyData:
// Disable data address translation
mfmsr %r6
li %r7, 0x10
andc %r6, %r6, %r7
mtmsr %r6
// Copy data
addi %r3, %r3, -1
addi %r4, %r4, -1
mtctr %r5
SCKernelCopyData_loop:
lbzu %r5, 1(%r4)
stbu %r5, 1(%r3)
bdnz SCKernelCopyData_loop
// Enable data address translation
ori %r6, %r6, 0x10
mtmsr %r6
blr
.global SC_0x25_KernelCopyData
SC_0x25_KernelCopyData:
li %r0, 0x2500
sc
blr
.globl KernelPatches
KernelPatches:
# store the old DBAT0
mfdbatu r5, 0
mfdbatl r6, 0
# memory barrier
eieio
isync
# setup DBAT0 for access to kernel code memory
lis r3, 0xFFF0
ori r3, r3, 0x0002
mtdbatu 0, r3
lis r3, 0xFFF0
ori r3, r3, 0x0032
mtdbatl 0, r3
# memory barrier
eieio
isync
# SaveAndResetDataBATs_And_SRs hook setup, but could be any BAT function though
# just chosen because its simple
lis r3, BAT_SETUP_HOOK_ADDR@h
ori r3, r3, BAT_SETUP_HOOK_ADDR@l
# make the kernel setup our section in IBAT4 and
# jump to our function to restore the replaced instructions
lis r4, 0x3ce0 # lis r7, BAT4L_VAL@h
ori r4, r4, BAT4L_VAL@h
stw r4, 0x00(r3)
lis r4, 0x60e7 # ori r7, r7, BAT4L_VAL@l
ori r4, r4, BAT4L_VAL@l
stw r4, 0x04(r3)
lis r4, 0x7cf1 # mtspr 561, r7
ori r4, r4, 0x8ba6
stw r4, 0x08(r3)
lis r4, 0x3ce0 # lis r7, BAT4U_VAL@h
ori r4, r4, BAT4U_VAL@h
stw r4, 0x0C(r3)
lis r4, 0x60e7 # ori r7, r7, BAT4U_VAL@l
ori r4, r4, BAT4U_VAL@l
stw r4, 0x10(r3)
lis r4, 0x7cf0 # mtspr 560, r7
ori r4, r4, 0x8ba6
stw r4, 0x14(r3)
lis r4, 0x7c00 # eieio
ori r4, r4, 0x06ac
stw r4, 0x18(r3)
lis r4, 0x4c00 # isync
ori r4, r4, 0x012c
stw r4, 0x1C(r3)
lis r4, 0x7ce8 # mflr r7
ori r4, r4, 0x02a6
stw r4, 0x20(r3)
lis r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@h # bla BAT_SETUP_HOOK_ENTRY
ori r4, r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@l
stw r4, 0x24(r3)
# flush and invalidate the replaced instructions
lis r3, (BAT_SETUP_HOOK_ADDR & ~31)@h
ori r3, r3, (BAT_SETUP_HOOK_ADDR & ~31)@l
dcbf 0, r3
icbi 0, r3
lis r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@h
ori r3, r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@l
dcbf 0, r3
icbi 0, r3
sync
# setup IBAT4 for core 1 at this position (not really required but wont hurt)
# IBATL 4
lis r3, BAT4L_VAL@h
ori r3, r3, BAT4L_VAL@l
mtspr 561, r3
# IBATU 4
lis r3, BAT4U_VAL@h
ori r3, r3, BAT4U_VAL@l
mtspr 560, r3
# memory barrier
eieio
isync
# write "nop" to some positions
lis r4, 0x6000
# nop on IBATU 4 and DBAT 5 set/reset
#ifdef BAT_SET_NOP_ADDR_1
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_1)
#endif
#ifdef BAT_SET_NOP_ADDR_2
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_2)
#endif
#ifdef BAT_SET_NOP_ADDR_3
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_3)
#endif
#ifdef BAT_SET_NOP_ADDR_4
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_4)
#endif
#ifdef BAT_SET_NOP_ADDR_5
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_5)
#endif
#ifdef BAT_SET_NOP_ADDR_6
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_6)
#endif
#ifdef BAT_SET_NOP_ADDR_7
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_7)
#endif
#if (defined(BAT_SET_NOP_ADDR_8) && defined(BAT_SET_NOP_ADDR_9))
# memory barrier
eieio
isync
# setup DBAT0 for access to kernel code memory
lis r3, 0xFFEE
ori r3, r3, 0x0002
mtdbatu 0, r3
lis r3, 0xFFEE
ori r3, r3, 0x0032
mtdbatl 0, r3
# memory barrier
eieio
isync
# write "nop" to some positions
lis r4, 0x6000
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_8)
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_9)
#endif
# memory barrier
eieio
isync
# restore DBAT 0 and return from interrupt
mtdbatu 0, r5
mtdbatl 0, r6
# memory barrier
eieio
isync
blr