diff --git a/Makefile b/Makefile index 01c263d..5959325 100644 --- a/Makefile +++ b/Makefile @@ -35,8 +35,8 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) -bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/k11modulespatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h $(dir_build)/injector.h $(dir_build)/loader.h - +bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/k11modulespatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/twl_k11modulespatch.h \ + $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h $(dir_build)/injector.h $(dir_build)/loader.h .PHONY: all all: launcher a9lh ninjhax @@ -106,6 +106,11 @@ $(dir_build)/svcGetCFWInfopatch.h: $(dir_patches)/svcGetCFWInfo.s @armips $< @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 @mkdir -p "$(@D)" @$(MAKE) -C $(dir_injector) diff --git a/patches/twl_k11modules.s b/patches/twl_k11modules.s new file mode 100644 index 0000000..dcda791 --- /dev/null +++ b/patches/twl_k11modules.s @@ -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 . +; +; 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 \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 466a5c7..be22917 100755 --- a/source/firm.c +++ b/source/firm.c @@ -44,7 +44,7 @@ static const firmSectionHeader *section; u32 config, emuOffset; -bool isN3DS, isDevUnit; +bool isN3DS, isDevUnit, isFirmlaunch; FirmwareSource firmSource; @@ -101,7 +101,7 @@ void main(void) isFirmlaunch = false; firmType = NATIVE_FIRM; - + //Determine if booting with A9LH isA9lh = !PDN_SPI_CNT; @@ -226,7 +226,7 @@ void main(void) } u32 firmVersion = loadFirm(firmType); - + switch(firmType) { case NATIVE_FIRM: @@ -241,7 +241,7 @@ void main(void) break; } - launchFirm(firmType, isFirmlaunch); + launchFirm(firmType); } static inline u32 loadFirm(FirmwareType firmType) @@ -346,7 +346,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 patchP9AccessChecks(process9Offset, process9Size); } - implementSvcGetCFWInfo((u8 *)firm + section[1].offset, section[1].size); + implementSvcGetCFWInfo(arm11Section1, section[1].size); } static inline void patchLegacyFirm(FirmwareType firmType) @@ -372,8 +372,9 @@ static inline void patchLegacyFirm(FirmwareType firmType) } applyLegacyFirmPatches((u8 *)firm, firmType); - fileWrite(arm9Section, "/luma/twl_arm9sec.bin", section[3].size); + if(firmType == TWL_FIRM) + patchTwlBg((u8 *)firm + section[1].offset); } static inline void patchSafeFirm(void) @@ -414,7 +415,7 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType) u8 *pos = arm11Section0, *end = pos + section[0].size; u32 n = 0; - u32 loaderIndex = 0, twlBgIndex = 0; + u32 loaderIndex = 0; while(pos < end) { @@ -438,35 +439,20 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType) } if(firmType == NATIVE_FIRM && memcmp(modules[n].name, "loader", 7) == 0) loaderIndex = n; - else if(firmType == TWL_FIRM && memcmp(modules[n].name, "TwlBg", 6) == 0) twlBgIndex = n; n++; } - u32 twlBgSize = 0; - if(firmType == NATIVE_FIRM && modules[loaderIndex].addr != NULL) { modules[loaderIndex].size = injector_size; modules[loaderIndex].addr = injector; } - else if(firmType == TWL_FIRM) - { - twlBgSize = getFileSize("/luma/TwlBg.cxi"); - if(twlBgSize != 0) - { - modules[twlBgIndex].size = twlBgSize; - modules[twlBgIndex].addr = NULL; - } - } - pos = section[0].address; for(u32 i = 0; i < n; i++) { - if(firmType == TWL_FIRM && i == twlBgIndex && twlBgSize != 0) - fileRead(pos, "/luma/TwlBg.cxi"); - else if(modules[i].addr != NULL) + if(modules[i].addr != NULL) memcpy(pos, modules[i].addr, modules[i].size); else { @@ -482,7 +468,7 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType) } } -static inline void launchFirm(FirmwareType firmType, bool isFirmlaunch) +static inline void launchFirm(FirmwareType firmType) { //If we're booting NATIVE_FIRM, section0 needs to be copied separately to inject 3ds_injector u32 sectionNum; diff --git a/source/firm.h b/source/firm.h index 7437b3e..84c74ed 100644 --- a/source/firm.h +++ b/source/firm.h @@ -24,11 +24,6 @@ #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 typedef struct firmSectionHeader { u32 offset; @@ -59,4 +54,4 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 static inline void patchLegacyFirm(FirmwareType firmType); static inline void patchSafeFirm(void); static inline void copySection0AndInjectSystemModules(FirmwareType firmType); -static inline void launchFirm(FirmwareType firmType, bool isFirmlaunch); \ No newline at end of file +static inline void launchFirm(FirmwareType firmType); \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index 8f527ed..eab35ec 100644 --- a/source/patches.c +++ b/source/patches.c @@ -26,6 +26,7 @@ #include "../build/rebootpatch.h" #include "../build/svcGetCFWInfopatch.h" #include "../build/k11modulespatch.h" +#include "../build/twl_k11modulespatch.h" static u32 *arm11ExceptionsPage = NULL; static u32 *arm11SvcTable = NULL; @@ -302,7 +303,7 @@ void patchUnitInfoValueSet(u8 *pos, u32 size) u8 *off = memsearch(pos, pattern, size, 4); - off[0] = (*(vu8 *)0x10010010 == 0) ? 1 : 0; + off[0] = (CFG_UNITINFO == 0) ? 1 : 0; off[3] = 0xE3; } @@ -428,3 +429,21 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType) } } } + +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); +} \ No newline at end of file diff --git a/source/patches.h b/source/patches.h index ee3b54a..52b1c38 100644 --- a/source/patches.h +++ b/source/patches.h @@ -53,4 +53,5 @@ void patchP9AccessChecks(u8 *pos, u32 size); void patchUnitInfoValueSet(u8 *pos, u32 size); void reimplementSvcBackdoor(u8 *pos, u32 size); void implementSvcGetCFWInfo(u8 *pos, u32 size); -void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); \ No newline at end of file +void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); +void patchTwlBg(u8 *pos); diff --git a/source/screen.h b/source/screen.h index a7af345..1e86289 100644 --- a/source/screen.h +++ b/source/screen.h @@ -29,7 +29,6 @@ #include "types.h" -#define PDN_GPU_CNT (*(vu8 *)0x10141200) #define ARM11_STUB_ADDRESS (0x25000000 - 0x30) //It's currently only 0x28 bytes large. We're putting 0x30 just to be sure here #define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)(); diff --git a/source/types.h b/source/types.h index 979db43..0aa6fc5 100644 --- a/source/types.h +++ b/source/types.h @@ -26,6 +26,13 @@ #include #include +#define CFG_BOOTENV (*(vu32 *)0x10010000) +#define CFG_UNITINFO (*(vu8 *)0x10010010) + +#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC) +#define PDN_SPI_CNT (*(vu32 *)0x101401C0) +#define PDN_GPU_CNT (*(vu8 *)0x10141200) + //Common data types typedef uint8_t u8; typedef uint16_t u16; diff --git a/source/utils.c b/source/utils.c index a7d3989..3a931f9 100644 --- a/source/utils.c +++ b/source/utils.c @@ -27,6 +27,8 @@ #include "draw.h" #include "cache.h" +extern bool isFirmlaunch; + u32 waitInput(void) { u32 pressedKey = 0, @@ -56,7 +58,7 @@ u32 waitInput(void) void mcuReboot(void) { - if(PDN_GPU_CNT != 1) clearScreens(); + if(!isFirmlaunch && PDN_GPU_CNT != 1) clearScreens(); flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed @@ -66,7 +68,7 @@ void mcuReboot(void) void mcuPowerOff(void) { - if(PDN_GPU_CNT != 1) clearScreens(); + if(!isFirmlaunch && PDN_GPU_CNT != 1) clearScreens(); flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed