Compare commits

...

15 Commits

Author SHA1 Message Date
Aurora
c711ed6253 Added a different error for < 3.x NANDs as they can not be booted currently 2016-08-27 00:34:25 +02:00
Aurora
356268eae5 Welcome back to the 1,25s speed boost 2016-08-26 22:24:23 +02:00
Aurora
2dd64b8a92 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2016-08-26 21:38:36 +02:00
Aurora
b5cddedb7d Fix config derp 2016-08-26 21:38:03 +02:00
TuxSH
7afdc2b3b5 "Fix" the twlbg patches and make them optional 2016-08-26 19:09:14 +02:00
Aurora
60c4956290 Fix wrong bootconfig being picked up by 3ds_injector, cleanup 2016-08-26 18:44:39 +02:00
TuxSH
7331a919e4 Fix bug. 2016-08-25 18:53:37 +02:00
TuxSH
33238cee54 Remove loading of /luma/TwlBg.cxi, fix bugs. 2016-08-25 16:39:43 +02:00
TuxSH
384dd2ad81 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))
2016-08-25 00:13:43 +02:00
TuxSH
74ac76ba84 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2016-08-21 22:09:47 +02:00
TuxSH
253e031f83 Add support for loading /luma/TwlBg.cxi (on dev branch this will take precedence) 2016-08-21 22:09:27 +02:00
TuxSH
ef1ecf859c Update draw.c 2016-08-20 19:59:25 +02:00
TuxSH
a302ad3bea R.I.P boot speed boost (for now) 2016-08-20 18:45:56 +02:00
TuxSH
b87dadbb72 Update patches.c 2016-08-18 00:36:28 +02:00
TuxSH
50a2424001 Implement svcGetCFWInfo in place of svc 0x2e (which is stubbed). Luma3DS now boots ca. 1.5s faster
Fix bug in pin.c where the START button wasn't recognized as well.
2016-08-17 23:47:30 +02:00
16 changed files with 443 additions and 99 deletions

View File

@@ -13,6 +13,7 @@ OC := arm-none-eabi-objcopy
name := Luma3DS
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i')
commit := $(shell git rev-parse --short=8 HEAD)
dir_source := source
dir_patches := patches
@@ -32,7 +33,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)/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
all: launcher a9lh ninjhax
@@ -91,6 +93,16 @@ $(dir_build)/rebootpatch.h: $(dir_patches)/reboot.s
@armips $<
@bin2c -o $@ -n reboot $(@D)/reboot.bin
$(dir_build)/svcGetCFWInfopatch.h: $(dir_patches)/svcGetCFWInfo.s
@mkdir -p "$(@D)"
@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)
@@ -102,6 +114,7 @@ $(dir_build)/loader.h: $(dir_loader)/Makefile
$(dir_build)/memory.o: CFLAGS += -O3
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
$(dir_build)/patches.o: CFLAGS += -DREVISION=\"$(revision)\" -DCOMMIT_HASH="0x$(commit)"
$(dir_build)/%.o: $(dir_source)/%.c $(bundled)
@mkdir -p "$(@D)"

View File

@@ -3,12 +3,7 @@
#include "patcher.h"
#include "ifile.h"
#ifndef PATH_MAX
#define PATH_MAX 255
#define CONFIG(a) (((loadConfig() >> (a + 16)) & 1) != 0)
#define MULTICONFIG(a) ((loadConfig() >> (a * 2 + 6)) & 3)
#define BOOTCONFIG(a, b) ((loadConfig() >> a) & b)
#endif
static CFWInfo info = {0};
static int memcmp(const void *buf1, const void *buf2, u32 size)
{
@@ -90,6 +85,28 @@ static int fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int f
return IFile_Open(file, archiveId, archivePath, filePath, flags);
}
int __attribute__((naked)) svcGetCFWInfo(CFWInfo __attribute__((unused)) *out)
{
__asm__ volatile("svc 0x2E; bx lr");
}
static void loadCFWInfo(void)
{
static bool infoLoaded = false;
if(!infoLoaded)
{
svcGetCFWInfo(&info);
IFile file;
if(BOOTCONFIG(5, 1) && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted
{
IFile_Close(&file);
}
infoLoaded = true;
}
}
static bool secureInfoExists(void)
{
static bool exists = false;
@@ -107,24 +124,6 @@ static bool secureInfoExists(void)
return exists;
}
static u32 loadConfig(void)
{
static u32 config = 0;
if(!config)
{
IFile file;
if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/luma/config.bin", FS_OPEN_READ)))
{
u64 total;
if(R_SUCCEEDED(IFile_Read(&file, &total, &config, 4))) config |= 1 << 4;
IFile_Close(&file);
}
}
return config;
}
static void progIdToStr(char *strEnd, u64 progId)
{
while(progId)
@@ -319,6 +318,8 @@ static void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHandleOff
void patchCode(u64 progId, u8 *code, u32 size)
{
loadCFWInfo();
switch(progId)
{
case 0x0004003000008F02LL: // USA Menu

View File

@@ -2,4 +2,24 @@
#include <3ds/types.h>
#define PATH_MAX 255
#define CONFIG(a) (((info.config >> (a + 16)) & 1) != 0)
#define MULTICONFIG(a) ((info.config >> (a * 2 + 6)) & 3)
#define BOOTCONFIG(a, b) ((info.config >> a) & b)
typedef struct __attribute__((packed))
{
char magic[4];
u8 versionMajor;
u8 versionMinor;
u8 versionBuild;
u8 flags; /* bit 0: dev branch; bit 1: is release */
u32 commitHash;
u32 config;
} CFWInfo;
void patchCode(u64 progId, u8 *code, u32 size);

48
patches/svcGetCFWInfo.s Normal file
View File

@@ -0,0 +1,48 @@
;
; 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/svcGetCFWInfo.bin", 0
.arm
adr r1, infoStart
add r2, r0, #(infoEnd - infoStart)
loop:
ldrb r3, [r1], #1
strbt r3, [r0], #1
cmp r0, r2
blo loop
mov r0, #0
bx lr
.pool
infoStart:
.ascii "LUMA" ; magic
.word 0 ; version
.word 0 ; truncated commit hash
.word 0 ; config
infoEnd:
.close

144
patches/twl_k11modules.s Normal file
View 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 0x83, 0x50, 0xf2, 0xa4, 0xb0, 0xe2, 0xc2, 0xd6 ; (decrypted = 0x02, 0x61, 0xc6, 0xe3, 0x08, 0x60, 0x87, 0xe5)
patchesEnd:
.pool
.close

View File

@@ -24,10 +24,9 @@
#include "utils.h"
#include "screen.h"
#include "draw.h"
#include "fs.h"
#include "buttons.h"
void configureCFW(const char *configPath)
void configureCFW(void)
{
initScreens();
@@ -44,7 +43,8 @@ void configureCFW(const char *configPath)
"( ) Show current NAND in System Settings",
"( ) Show GBA boot screen in patched AGB_FIRM",
"( ) Display splash screen before payloads",
"( ) Use a PIN" };
"( ) Use a PIN",
"( ) Enable experimental TwlBg patches" };
struct multiOption {
int posXs[4];
@@ -193,13 +193,6 @@ void configureCFW(const char *configPath)
for(u32 i = 0; i < singleOptionsAmount; i++)
config |= (singleOptions[i].enabled ? 1 : 0) << (i + 16);
if(!fileWrite(&config, configPath, 4))
{
createDirectory("luma");
if(!fileWrite(&config, configPath, 4))
error("Error writing the configuration file");
}
//Wait for the pressed buttons to change
while(HID_PAD == BUTTON_START);
}

View File

@@ -30,4 +30,4 @@
extern u32 config;
void configureCFW(const char *configPath);
void configureCFW(void);

View File

@@ -43,7 +43,7 @@ static inline int strlen(const char *string)
bool loadSplash(void)
{
//Don't delay boot nor init the screens if no splash image is on the SD
if(getFileSize("/luma/splash.bin") + getFileSize("/luma/splash.bin") == 0)
if(getFileSize("/luma/splash.bin") + getFileSize("/luma/splashbottom.bin") == 0)
return false;
initScreens();

View File

@@ -43,16 +43,17 @@ static const firmSectionHeader *section;
u32 config,
emuOffset;
bool isN3DS, isDevUnit;
bool isN3DS,
isDevUnit,
isFirmlaunch;
FirmwareSource firmSource;
void main(void)
{
bool isFirmlaunch,
isA9lh;
bool isA9lh;
u32 newConfig,
u32 configTemp,
emuHeader;
FirmwareType firmType;
@@ -101,7 +102,8 @@ void main(void)
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
bool useSysAsDefault = isA9lh ? CONFIG(1) : false;
newConfig = (u32)isA9lh << 3;
//Save old options and begin saving the new boot configuration
configTemp = (config & 0xFFFFFFC0) | ((u32)isA9lh << 3);
//If it's a MCU reboot, try to force boot options
if(isA9lh && CFG_BOOTENV)
@@ -114,7 +116,7 @@ void main(void)
needConfig = DONT_CONFIGURE;
//Flag to prevent multiple boot options-forcing
newConfig |= 1 << 4;
configTemp |= 1 << 4;
}
/* Else, force the last used boot options unless a button is pressed
@@ -142,7 +144,7 @@ void main(void)
if(shouldLoadConfigurationMenu)
{
configureCFW(configPath);
configureCFW();
if(!pinExists && CONFIG(7)) newPin();
@@ -156,6 +158,9 @@ void main(void)
{
nandType = FIRMWARE_SYSNAND;
firmSource = FIRMWARE_SYSNAND;
//Flag to tell loader to init SD
configTemp |= 1 << 5;
}
else
{
@@ -204,17 +209,21 @@ void main(void)
if(!isFirmlaunch)
{
newConfig |= (u32)nandType | ((u32)firmSource << 2);
configTemp |= (u32)nandType | ((u32)firmSource << 2);
/* If the boot configuration is different from previously, overwrite it.
/* If the configuration is different from previously, overwrite it.
Just the no-forcing flag being set is not enough */
if((newConfig & 0x2F) != (config & 0x3F))
if((configTemp & 0xFFFFFFEF) != config)
{
//Preserve user settings (last 26 bits)
newConfig |= config & 0xFFFFFFC0;
//Merge the new options and new boot configuration
config = (config & 0xFFFFFFC0) | (configTemp & 0x3F);
if(!fileWrite(&newConfig, configPath, 4))
error("Error writing the configuration file");
if(!fileWrite(&config, configPath, 4))
{
createDirectory("luma");
if(!fileWrite(&config, configPath, 4))
error("Error writing the configuration file");
}
}
}
@@ -234,7 +243,7 @@ void main(void)
break;
}
launchFirm(firmType, isFirmlaunch);
launchFirm(firmType);
}
static inline u32 loadFirm(FirmwareType firmType)
@@ -246,6 +255,11 @@ static inline u32 loadFirm(FirmwareType firmType)
if(!isN3DS && firmType == NATIVE_FIRM && firmVersion < 0x25)
{
//We can't boot < 3.x NANDs
if(firmVersion < 0x18)
error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it.");
//We can't boot a 4.x NATIVE_FIRM, load one from SD
if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68)
error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot");
@@ -260,6 +274,7 @@ static inline u32 loadFirm(FirmwareType firmType)
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh)
{
u8 *arm9Section = (u8 *)firm + section[2].offset;
u8 *arm11Section1 = (u8 *)firm + section[1].offset;
if(isN3DS)
{
@@ -299,8 +314,10 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
patchTitleInstallMinVersionCheck(process9Offset, process9Size);
//Restore svcBackdoor
reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size);
reimplementSvcBackdoor(arm11Section1, section[1].size);
}
implementSvcGetCFWInfo(arm11Section1, section[1].size);
}
static inline void patchLegacyFirm(FirmwareType firmType)
@@ -313,6 +330,9 @@ static inline void patchLegacyFirm(FirmwareType firmType)
}
applyLegacyFirmPatches((u8 *)firm, firmType);
if(firmType == TWL_FIRM && CONFIG(8))
patchTwlBg((u8 *)firm + section[1].offset);
}
static inline void patchSafeFirm(void)
@@ -330,25 +350,44 @@ static inline void patchSafeFirm(void)
else patchFirmWriteSafe(arm9Section, section[2].size);
}
static inline void copySection0AndInjectLoader(void)
static inline void copySection0AndInjectSystemModules(void)
{
u8 *arm11Section0 = (u8 *)firm + section[0].offset;
u32 loaderSize;
u32 loaderOffset = getLoader(arm11Section0, &loaderSize);
struct
{
u32 size;
const u8 *addr;
} modules[5];
memcpy(section[0].address, arm11Section0, loaderOffset);
memcpy(section[0].address + loaderOffset, injector, injector_size);
memcpy(section[0].address + loaderOffset + injector_size, arm11Section0 + loaderOffset + loaderSize, section[0].size - (loaderOffset + loaderSize));
u32 n = 0,
loaderIndex;
u8 *pos = arm11Section0;
for(u8 *end = pos + section[0].size; pos < end; pos += modules[n++].size)
{
modules[n].addr = pos;
modules[n].size = *(u32 *)(pos + 0x104) * 0x200;
if(memcmp(modules[n].addr + 0x200, "loader", 7) == 0) loaderIndex = n;
}
modules[loaderIndex].addr = injector;
modules[loaderIndex].size = injector_size;
pos = section[0].address;
for(u32 i = 0; i < n; pos += modules[i++].size)
memcpy(pos, modules[i].addr, modules[i].size);
}
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;
if(firmType == NATIVE_FIRM)
{
copySection0AndInjectLoader();
copySection0AndInjectSystemModules();
sectionNum = 1;
}
else sectionNum = 0;

View File

@@ -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;
@@ -58,5 +53,5 @@ static inline u32 loadFirm(FirmwareType firmType);
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh);
static inline void patchLegacyFirm(FirmwareType firmType);
static inline void patchSafeFirm(void);
static inline void copySection0AndInjectLoader(void);
static inline void launchFirm(FirmwareType firmType, bool isFirmlaunch);
static inline void copySection0AndInjectSystemModules(void);
static inline void launchFirm(FirmwareType firmType);

View File

@@ -24,6 +24,49 @@
#include "memory.h"
#include "config.h"
#include "../build/rebootpatch.h"
#include "../build/svcGetCFWInfopatch.h"
#include "../build/twl_k11modulespatch.h"
static u32 *arm11ExceptionsPage = NULL;
static u32 *arm11SvcTable = NULL;
static u32 *arm11SvcHandler = NULL;
static u8 *freeK11Space = NULL; //other than the one used for svcBackdoor
static void findArm11ExceptionsPageAndSvcHandlerAndTable(u8 *pos, u32 size)
{
const u8 arm11ExceptionsPagePattern[] = {0x00, 0xB0, 0x9C, 0xE5};
if(arm11ExceptionsPage == NULL) arm11ExceptionsPage = (u32 *)memsearch(pos, arm11ExceptionsPagePattern, size, 4) - 0xB;
if((arm11SvcTable == NULL || arm11SvcHandler == NULL) && arm11ExceptionsPage != NULL)
{
u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch
arm11SvcHandler = arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address
while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL)
}
}
static void findFreeK11Space(u8 *pos, u32 size)
{
if(freeK11Space == NULL)
{
const u8 bogus_pattern[] = { 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF,
0x2F, 0xE1, 0x00, 0x10, 0xA0, 0xE3, 0x00, 0x10, 0xC0, 0xE5,
0x1E, 0xFF, 0x2F, 0xE1 };
u32 *someSpace = (u32 *)memsearch(pos, bogus_pattern, size, 24);
// We couldn't find the place where to begin our search of an empty block
if (someSpace == NULL)
return;
// Advance until we reach the padding area (filled with 0xFF)
u32 *freeSpace;
for(freeSpace = someSpace; *freeSpace != 0xFFFFFFFF; freeSpace++);
freeK11Space = (u8 *)freeSpace;
}
}
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
{
@@ -111,25 +154,49 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0
0x11, 0xFF, 0x2F, 0xE1}; //bx r1
const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; //cpsid aif
u32 *exceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB;
findArm11ExceptionsPageAndSvcHandlerAndTable(pos, size);
u32 svcOffset = (-((exceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch
u32 *svcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address
while(*svcTable) svcTable++; //Look for SVC0 (NULL)
if(svcTable[0x7B] == 0)
if(!arm11SvcTable[0x7B])
{
u32 *freeSpace;
for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
for(freeSpace = arm11ExceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
memcpy(freeSpace, svcBackdoor, 40);
svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage);
arm11SvcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)arm11ExceptionsPage);
}
}
void implementSvcGetCFWInfo(u8 *pos, u32 size)
{
const char *rev = REVISION;
bool isRelease;
findArm11ExceptionsPageAndSvcHandlerAndTable(pos, size);
findFreeK11Space(pos, size);
memcpy(freeK11Space, svcGetCFWInfo, svcGetCFWInfo_size);
CFWInfo *info = (CFWInfo *)memsearch(freeK11Space, "LUMA", svcGetCFWInfo_size, 4);
info->commitHash = COMMIT_HASH;
info->config = config;
info->versionMajor = (u8)(rev[1] - '0');
info->versionMinor = (u8)(rev[3] - '0');
if(rev[4] == '.')
{
info->versionBuild = (u8)(rev[5] - '0');
isRelease = rev[6] == 0;
}
else
isRelease = rev[4] == 0;
info->flags = 0 /* master branch */ | (((isRelease) ? 1 : 0) << 1) /* is release */;
arm11SvcTable[0x2E] = 0xFFF00000 + freeK11Space - pos; //stubbed svc
freeK11Space += svcGetCFWInfo_size;
}
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
{
const u8 pattern[] = {0x0A, 0x81, 0x42, 0x02};
@@ -180,19 +247,20 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType)
}
}
u32 getLoader(u8 *pos, u32 *loaderSize)
void patchTwlBg(u8 *pos)
{
u8 *off = pos;
u32 size;
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);
while(true)
{
size = *(u32 *)(off + 0x104) * 0x200;
if(*(u32 *)(off + 0x200) == 0x64616F6C) break;
off += size;
}
*loaderSize = size;
return (u32)(off - pos);
src2[0] = 0xF000 | ((((u32)dst - (u32)src2 - 4) & (0xFFF << 11)) >> 12);
src2[1] = 0xE800 | ((((u32)dst - (u32)src2 - 4) & 0xFFF) >> 1);
}

View File

@@ -33,7 +33,22 @@ typedef struct patchData {
u32 type;
} patchData;
typedef struct __attribute__((packed))
{
char magic[4];
u8 versionMajor;
u8 versionMinor;
u8 versionBuild;
u8 flags;
u32 commitHash;
u32 config;
} CFWInfo;
extern bool isN3DS;
extern u32 config;
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
void patchSignatureChecks(u8 *pos, u32 size);
@@ -42,5 +57,6 @@ void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
void patchFirmWrites(u8 *pos, u32 size);
void patchFirmWriteSafe(u8 *pos, u32 size);
void reimplementSvcBackdoor(u8 *pos, u32 size);
void implementSvcGetCFWInfo(u8 *pos, u32 size);
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
u32 getLoader(u8 *pos, u32 *loaderSize);
void patchTwlBg(u8 *pos);

View File

@@ -131,12 +131,11 @@ void verifyPin(PINData *in)
}
while(!(pressed & PIN_BUTTONS));
pressed &= PIN_BUTTONS & ~BUTTON_START;
if(!pressed) continue;
if(pressed & BUTTON_START) mcuPowerOff();
pressed &= PIN_BUTTONS & ~BUTTON_START;
if(!pressed) continue;
char key = PINKeyToLetter(pressed);
enteredPassword[cnt++] = (u8)key; // add character to password.

View File

@@ -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)();

View File

@@ -26,6 +26,13 @@
#include <stdlib.h>
#include <stdbool.h>
#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;

View File

@@ -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