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.
This commit is contained in:
TuxSH 2016-08-17 23:47:30 +02:00
parent 4f8c66b2b7
commit 50a2424001
7 changed files with 187 additions and 36 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,7 @@ 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)/injector.h $(dir_build)/loader.h
.PHONY: all
all: launcher a9lh ninjhax
@ -91,6 +92,11 @@ $(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)/injector.h: $(dir_injector)/Makefile
@mkdir -p "$(@D)"
@$(MAKE) -C $(dir_injector)
@ -102,6 +108,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,11 +3,39 @@
#include "patcher.h"
#include "ifile.h"
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;
CFWInfo info = {0};
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);
infoLoaded = true;
}
#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)
#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)
#endif
static int memcmp(const void *buf1, const void *buf2, u32 size)
@ -107,24 +135,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 +329,7 @@ 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

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

View File

@ -301,6 +301,8 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
//Restore svcBackdoor
reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size);
}
implementSvcGetCFWInfo((u8 *)firm + section[1].offset, section[1].size);
}
static inline void patchLegacyFirm(FirmwareType firmType)

View File

@ -24,6 +24,49 @@
#include "memory.h"
#include "config.h"
#include "../build/rebootpatch.h"
#include "../build/svcGetCFWInfopatch.h"
#include "fs.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,65 @@ 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);
}
}
extern u32 config;
void implementSvcGetCFWInfo(u8 *pos, u32 size)
{
typedef struct __attribute__((packed))
{
char magic[4];
u8 versionMajor;
u8 versionMinor;
u8 versionBuild;
u8 flags;
u32 commitHash;
u32 config;
} CFWInfo;
const char *rev = REVISION;
bool isRelease = false;
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};

View File

@ -42,5 +42,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);

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.