Implement on-the-fly patching of TwlBg
(and port the patches from https://github.com/ahezard/twl_firm_patcher; big thanks to ahezard and people mentioned in this page; also to Subv for the original patching idea (for NATIVE_FIRM))
This commit is contained in:
parent
74ac76ba84
commit
384dd2ad81
8
Makefile
8
Makefile
@ -33,7 +33,8 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||||
|
|
||||||
bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/injector.h $(dir_build)/loader.h
|
bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/twl_k11modulespatch.h \
|
||||||
|
$(dir_build)/injector.h $(dir_build)/loader.h
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: launcher a9lh ninjhax
|
all: launcher a9lh ninjhax
|
||||||
@ -97,6 +98,11 @@ $(dir_build)/svcGetCFWInfopatch.h: $(dir_patches)/svcGetCFWInfo.s
|
|||||||
@armips $<
|
@armips $<
|
||||||
@bin2c -o $@ -n svcGetCFWInfo $(@D)/svcGetCFWInfo.bin
|
@bin2c -o $@ -n svcGetCFWInfo $(@D)/svcGetCFWInfo.bin
|
||||||
|
|
||||||
|
$(dir_build)/twl_k11modulespatch.h: $(dir_patches)/twl_k11modules.s
|
||||||
|
@mkdir -p "$(@D)"
|
||||||
|
@armips $<
|
||||||
|
@bin2c -o $@ -n twl_k11modules $(@D)/twl_k11modules.bin
|
||||||
|
|
||||||
$(dir_build)/injector.h: $(dir_injector)/Makefile
|
$(dir_build)/injector.h: $(dir_injector)/Makefile
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
@$(MAKE) -C $(dir_injector)
|
@$(MAKE) -C $(dir_injector)
|
||||||
|
144
patches/twl_k11modules.s
Normal file
144
patches/twl_k11modules.s
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
;
|
||||||
|
; This file is part of Luma3DS
|
||||||
|
; Copyright (C) 2016 Aurora Wright, TuxSH
|
||||||
|
;
|
||||||
|
; This program is free software: you can redistribute it and/or modify
|
||||||
|
; it under the terms of the GNU General Public License as published by
|
||||||
|
; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
; (at your option) any later version.
|
||||||
|
;
|
||||||
|
; This program is distributed in the hope that it will be useful,
|
||||||
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
; GNU General Public License for more details.
|
||||||
|
;
|
||||||
|
; You should have received a copy of the GNU General Public License
|
||||||
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
;
|
||||||
|
; Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified
|
||||||
|
; reasonable legal notices or author attributions in that material or in the Appropriate Legal
|
||||||
|
; Notices displayed by works containing it.
|
||||||
|
;
|
||||||
|
|
||||||
|
.arm.little
|
||||||
|
|
||||||
|
.create "build/twl_k11modules.bin", 0
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.arm
|
||||||
|
|
||||||
|
patch:
|
||||||
|
; r4: Pointer to a pointer to the exheader of the current NCCH
|
||||||
|
; sp + 0xb0 - 0xa4: Pointer to the memory location where the NCCH text was loaded
|
||||||
|
|
||||||
|
add r3, sp, #(0xb0 - 0xa4)
|
||||||
|
add r1, sp, #(0xb0 - 0xac)
|
||||||
|
|
||||||
|
push {r0-r11, lr}
|
||||||
|
|
||||||
|
ldr r9, [r3] ; load the address of the code section
|
||||||
|
ldr r8, [r4] ; load the address of the exheader
|
||||||
|
|
||||||
|
ldr r7, [r8, #0x200] ; low titleID
|
||||||
|
ldr r6, =#0x000001ff
|
||||||
|
cmp r7, r6
|
||||||
|
bne end
|
||||||
|
|
||||||
|
ldr r7, =#0xabcdabcd ; offset of the dev launcher (will be replaced later)
|
||||||
|
add r7, r9
|
||||||
|
|
||||||
|
adr r5, patchesStart
|
||||||
|
add r6, r5, #(patchesEnd - patchesStart)
|
||||||
|
|
||||||
|
patchLoop:
|
||||||
|
ldrh r0, [r5, #4]
|
||||||
|
cmp r0, #0
|
||||||
|
moveq r4, r9
|
||||||
|
movne r4, r7
|
||||||
|
|
||||||
|
ldrh r2, [r5, #6]
|
||||||
|
add r1, r5, #8
|
||||||
|
ldr r0, [r5]
|
||||||
|
add r0, r4
|
||||||
|
blx memcmp
|
||||||
|
cmp r0, #0
|
||||||
|
bne skipPatch
|
||||||
|
|
||||||
|
ldrh r2, [r5, #6]
|
||||||
|
add r1, r5, #0x08
|
||||||
|
add r1, r2
|
||||||
|
ldr r0, [r5]
|
||||||
|
add r0, r4
|
||||||
|
blx memcpy
|
||||||
|
|
||||||
|
skipPatch:
|
||||||
|
|
||||||
|
ldrh r0, [r5, #6]
|
||||||
|
add r5, r5, #0x08
|
||||||
|
add r5, r0,lsl#1
|
||||||
|
cmp r5, r6
|
||||||
|
blo patchLoop
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
pop {r0-r11, pc}
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
memcmp:
|
||||||
|
push {r4-r7, lr}
|
||||||
|
mov r4, #0
|
||||||
|
cmp_loop:
|
||||||
|
cmp r4, r2
|
||||||
|
bhs cmp_loop_end
|
||||||
|
ldrb r6, [r0, r4]
|
||||||
|
ldrb r7, [r1, r4]
|
||||||
|
add r4, #1
|
||||||
|
sub r6, r7
|
||||||
|
cmp r6, #0
|
||||||
|
beq cmp_loop
|
||||||
|
|
||||||
|
cmp_loop_end:
|
||||||
|
mov r0, r6
|
||||||
|
pop {r4-r7, pc}
|
||||||
|
|
||||||
|
memcpy:
|
||||||
|
push {r4-r5, lr}
|
||||||
|
mov r4, #0
|
||||||
|
|
||||||
|
copy_loop:
|
||||||
|
cmp r4, r2
|
||||||
|
bhs copy_loop_end
|
||||||
|
ldrb r5, [r1, r4]
|
||||||
|
strb r5, [r0, r4]
|
||||||
|
add r4, #1
|
||||||
|
b copy_loop
|
||||||
|
|
||||||
|
copy_loop_end:
|
||||||
|
pop {r4-r5, pc}
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
; Available space for patches: 152 bytes on N3DS, 666 on O3DS
|
||||||
|
|
||||||
|
patchesStart:
|
||||||
|
; SCFG_EXT bit31 patches, based on https://github.com/ahezard/twl_firm_patcher (credits where they're due)
|
||||||
|
|
||||||
|
.word 0x07368 ; offset
|
||||||
|
.halfword 1 ; type (0: relative to the start of TwlBg's code; 1: relative to the start of the dev SRL launcher)
|
||||||
|
.halfword 4 ; size (must be a multiple of 4)
|
||||||
|
.byte 0x94, 0x09, 0xfc, 0xed ; expected data (decrypted = 0x08, 0x60, 0x87, 0x05)
|
||||||
|
.byte 0x24, 0x09, 0xbc, 0xe9 ; patched data (decrypted = 0xb8, 0x60, 0xc7, 0x01)
|
||||||
|
|
||||||
|
.word 0xa5888
|
||||||
|
.halfword 1
|
||||||
|
.halfword 8
|
||||||
|
.byte 0x83, 0x30, 0x2e, 0xa4, 0xb0, 0xe2, 0xc2, 0xd6 ; (decrypted = 0x02, 0x01, 0x1a, 0xe3, 0x08, 0x60, 0x87, 0x05)
|
||||||
|
.byte 0x89, 0x53, 0xb2, 0xa4, 0xb0, 0xe2, 0xc2, 0xd6 ; (decrypted = 0x08, 0x62, 0x86, 0xe3, 0x08, 0x60, 0x87, 0xe5)
|
||||||
|
|
||||||
|
patchesEnd:
|
||||||
|
|
||||||
|
.pool
|
||||||
|
|
||||||
|
.close
|
@ -260,6 +260,7 @@ static inline u32 loadFirm(FirmwareType firmType)
|
|||||||
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh)
|
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh)
|
||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
||||||
|
u8 *arm11Section1 = (u8 *)firm + section[1].offset;
|
||||||
|
|
||||||
if(isN3DS)
|
if(isN3DS)
|
||||||
{
|
{
|
||||||
@ -299,10 +300,10 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
|||||||
patchTitleInstallMinVersionCheck(process9Offset, process9Size);
|
patchTitleInstallMinVersionCheck(process9Offset, process9Size);
|
||||||
|
|
||||||
//Restore svcBackdoor
|
//Restore svcBackdoor
|
||||||
reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size);
|
reimplementSvcBackdoor(arm11Section1, section[1].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
implementSvcGetCFWInfo((u8 *)firm + section[1].offset, section[1].size);
|
implementSvcGetCFWInfo(arm11Section1, section[1].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchLegacyFirm(FirmwareType firmType)
|
static inline void patchLegacyFirm(FirmwareType firmType)
|
||||||
@ -315,6 +316,9 @@ static inline void patchLegacyFirm(FirmwareType firmType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyLegacyFirmPatches((u8 *)firm, firmType);
|
applyLegacyFirmPatches((u8 *)firm, firmType);
|
||||||
|
|
||||||
|
if(firmType == TWL_FIRM)
|
||||||
|
patchTwlBg((u8 *)firm + section[1].offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchSafeFirm(void)
|
static inline void patchSafeFirm(void)
|
||||||
|
@ -24,11 +24,6 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC)
|
|
||||||
#define PDN_SPI_CNT (*(vu32 *)0x101401C0)
|
|
||||||
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
|
||||||
#define CFG_UNITINFO (*(vu8 *)0x10010010)
|
|
||||||
|
|
||||||
//FIRM Header layout
|
//FIRM Header layout
|
||||||
typedef struct firmSectionHeader {
|
typedef struct firmSectionHeader {
|
||||||
u32 offset;
|
u32 offset;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "../build/rebootpatch.h"
|
#include "../build/rebootpatch.h"
|
||||||
#include "../build/svcGetCFWInfopatch.h"
|
#include "../build/svcGetCFWInfopatch.h"
|
||||||
|
#include "../build/twl_k11modulespatch.h"
|
||||||
|
|
||||||
static u32 *arm11ExceptionsPage = NULL;
|
static u32 *arm11ExceptionsPage = NULL;
|
||||||
static u32 *arm11SvcTable = NULL;
|
static u32 *arm11SvcTable = NULL;
|
||||||
@ -260,4 +261,22 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void patchTwlBg(u8 *pos)
|
||||||
|
{
|
||||||
|
u8 *dst = pos + ((isN3DS) ? 0xFEA4 : 0xFCA0);
|
||||||
|
u16 *src1 = (u16 *)(pos + ((isN3DS) ? 0xE38 : 0xE3C)), *src2 = (u16 *)(pos + ((isN3DS) ? 0xE54 : 0xE58));
|
||||||
|
memcpy(dst, twl_k11modules, twl_k11modules_size); //install k11 hook
|
||||||
|
|
||||||
|
u32 *off;
|
||||||
|
for(off = (u32 *)dst; *off != 0xABCDABCD; off++);
|
||||||
|
*off = (isN3DS) ? 0xCDE88 : 0xCD5F8; //dev SRL launcher offset
|
||||||
|
|
||||||
|
//Construct BLX instructions:
|
||||||
|
src1[0] = 0xF000 | ((((u32)dst - (u32)src1 - 4) & (0xFFF << 11)) >> 12);
|
||||||
|
src1[1] = 0xE800 | ((((u32)dst - (u32)src1 - 4) & 0xFFF) >> 1);
|
||||||
|
|
||||||
|
src2[0] = 0xF000 | ((((u32)dst - (u32)src2 - 4) & (0xFFF << 11)) >> 12);
|
||||||
|
src2[1] = 0xE800 | ((((u32)dst - (u32)src2 - 4) & 0xFFF) >> 1);
|
||||||
}
|
}
|
@ -43,4 +43,5 @@ void patchFirmWrites(u8 *pos, u32 size);
|
|||||||
void patchFirmWriteSafe(u8 *pos, u32 size);
|
void patchFirmWriteSafe(u8 *pos, u32 size);
|
||||||
void reimplementSvcBackdoor(u8 *pos, u32 size);
|
void reimplementSvcBackdoor(u8 *pos, u32 size);
|
||||||
void implementSvcGetCFWInfo(u8 *pos, u32 size);
|
void implementSvcGetCFWInfo(u8 *pos, u32 size);
|
||||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
||||||
|
void patchTwlBg(u8 *pos);
|
@ -26,6 +26,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC)
|
||||||
|
#define PDN_SPI_CNT (*(vu32 *)0x101401C0)
|
||||||
|
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
||||||
|
#define CFG_UNITINFO (*(vu8 *)0x10010010)
|
||||||
|
|
||||||
//Common data types
|
//Common data types
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
|
Reference in New Issue
Block a user