Merge branch 'master' into developer
Conflicts: Makefile source/patches.c
This commit is contained in:
commit
1dd6a9821a
9
Makefile
9
Makefile
@ -13,6 +13,7 @@ OC := arm-none-eabi-objcopy
|
|||||||
|
|
||||||
name := Luma3DS
|
name := Luma3DS
|
||||||
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i')
|
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_source := source
|
||||||
dir_patches := patches
|
dir_patches := patches
|
||||||
@ -34,7 +35,7 @@ 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)/k11modulespatch.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)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h $(dir_build)/injector.h $(dir_build)/loader.h
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: launcher a9lh ninjhax
|
all: launcher a9lh ninjhax
|
||||||
@ -100,6 +101,11 @@ $(dir_build)/k11modulespatch.h: $(dir_patches)/k11modules.s
|
|||||||
@armips $<
|
@armips $<
|
||||||
@bin2c -o $@ -n k11modules $(@D)/k11modules.bin
|
@bin2c -o $@ -n k11modules $(@D)/k11modules.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
|
$(dir_build)/injector.h: $(dir_injector)/Makefile
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
@$(MAKE) -C $(dir_injector)
|
@$(MAKE) -C $(dir_injector)
|
||||||
@ -119,6 +125,7 @@ $(dir_build)/arm11_exceptions.h: $(dir_arm11_exceptions)/Makefile
|
|||||||
|
|
||||||
$(dir_build)/memory.o: CFLAGS += -O3
|
$(dir_build)/memory.o: CFLAGS += -O3
|
||||||
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) (dev) configuration\""
|
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) (dev) configuration\""
|
||||||
|
$(dir_build)/patches.o: CFLAGS += -DREVISION=\"$(revision)\" -DCOMMIT_HASH="0x$(commit)"
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c $(bundled)
|
$(dir_build)/%.o: $(dir_source)/%.c $(bundled)
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
|
@ -3,11 +3,39 @@
|
|||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
#include "ifile.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
|
#ifndef PATH_MAX
|
||||||
#define PATH_MAX 255
|
#define PATH_MAX 255
|
||||||
#define CONFIG(a) (((loadConfig() >> (a + 16)) & 1) != 0)
|
#define CONFIG(a) (((info.config >> (a + 16)) & 1) != 0)
|
||||||
#define MULTICONFIG(a) ((loadConfig() >> (a * 2 + 6)) & 3)
|
#define MULTICONFIG(a) ((info.config >> (a * 2 + 6)) & 3)
|
||||||
#define BOOTCONFIG(a, b) ((loadConfig() >> a) & b)
|
#define BOOTCONFIG(a, b) ((info.config >> a) & b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int memcmp(const void *buf1, const void *buf2, u32 size)
|
static int memcmp(const void *buf1, const void *buf2, u32 size)
|
||||||
@ -107,24 +135,6 @@ static bool secureInfoExists(void)
|
|||||||
return exists;
|
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)
|
static void progIdToStr(char *strEnd, u64 progId)
|
||||||
{
|
{
|
||||||
while(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)
|
void patchCode(u64 progId, u8 *code, u32 size)
|
||||||
{
|
{
|
||||||
|
loadCFWInfo();
|
||||||
switch(progId)
|
switch(progId)
|
||||||
{
|
{
|
||||||
case 0x0004003000008F02LL: // USA Menu
|
case 0x0004003000008F02LL: // USA Menu
|
||||||
|
48
patches/svcGetCFWInfo.s
Normal file
48
patches/svcGetCFWInfo.s
Normal 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
|
@ -339,6 +339,8 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
|||||||
patchK11ModuleChecks(arm11Section1, section[1].size);
|
patchK11ModuleChecks(arm11Section1, section[1].size);
|
||||||
patchP9AccessChecks(arm9Section, section[2].size);
|
patchP9AccessChecks(arm9Section, section[2].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implementSvcGetCFWInfo((u8 *)firm + section[1].offset, section[1].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchLegacyFirm(FirmwareType firmType)
|
static inline void patchLegacyFirm(FirmwareType firmType)
|
||||||
|
@ -25,11 +25,15 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "../build/rebootpatch.h"
|
#include "../build/rebootpatch.h"
|
||||||
#include "../build/k11modulespatch.h"
|
#include "../build/k11modulespatch.h"
|
||||||
|
#include "../build/svcGetCFWInfopatch.h"
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
static u32 *arm11ExceptionsPage = NULL;
|
static u32 *arm11ExceptionsPage = NULL;
|
||||||
static u32 *arm11SvcTable = NULL;
|
static u32 *arm11SvcTable = NULL;
|
||||||
static u32 *arm11SvcHandler = NULL;
|
static u32 *arm11SvcHandler = NULL;
|
||||||
|
|
||||||
|
static u8 *freeK11Space = NULL; //other than the one used for svcBackdoor
|
||||||
|
|
||||||
static void findArm11ExceptionsPageAndSvcHandlerAndTable(u8 *pos, u32 size)
|
static void findArm11ExceptionsPageAndSvcHandlerAndTable(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
const u8 arm11ExceptionsPagePattern[] = {0x00, 0xB0, 0x9C, 0xE5};
|
const u8 arm11ExceptionsPagePattern[] = {0x00, 0xB0, 0x9C, 0xE5};
|
||||||
@ -43,6 +47,28 @@ static void findArm11ExceptionsPageAndSvcHandlerAndTable(u8 *pos, u32 size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||||
{
|
{
|
||||||
u8 *off = memsearch(pos, "ess9", size, 4);
|
u8 *off = memsearch(pos, "ess9", size, 4);
|
||||||
@ -233,20 +259,9 @@ void patchK11ModuleChecks(u8 *pos, u32 size)
|
|||||||
// We have to detour a function in the ARM11 kernel because builtin modules
|
// We have to detour a function in the ARM11 kernel because builtin modules
|
||||||
// are compressed in memory and are only decompressed at runtime.
|
// are compressed in memory and are only decompressed at runtime.
|
||||||
|
|
||||||
// Find some padding space to add our code
|
findFreeK11Space(pos, size);
|
||||||
const u8 bogus_pattern[] = { 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF,
|
u8 *freeSpace = freeK11Space;
|
||||||
0x2F, 0xE1, 0x00, 0x10, 0xA0, 0xE3, 0x00, 0x10, 0xC0, 0xE5,
|
freeK11Space += k11modules_size;
|
||||||
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++);
|
|
||||||
|
|
||||||
// Inject our code into the free space
|
// Inject our code into the free space
|
||||||
memcpy(freeSpace, k11modules, k11modules_size);
|
memcpy(freeSpace, k11modules, k11modules_size);
|
||||||
@ -318,6 +333,52 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = 1 /* dev branch */ | (((isRelease) ? 1 : 0) << 1) /* is release */;
|
||||||
|
|
||||||
|
arm11SvcTable[0x2E] = 0xFFF00000 + freeK11Space - pos; //stubbed svc
|
||||||
|
freeK11Space += svcGetCFWInfo_size;
|
||||||
|
}
|
||||||
|
|
||||||
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
|
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
const u8 pattern[] = {0x0A, 0x81, 0x42, 0x02};
|
const u8 pattern[] = {0x0A, 0x81, 0x42, 0x02};
|
||||||
|
@ -52,5 +52,6 @@ void patchK11ModuleChecks(u8 *pos, u32 size);
|
|||||||
void patchP9AccessChecks(u8 *pos, u32 size);
|
void patchP9AccessChecks(u8 *pos, u32 size);
|
||||||
void patchUnitInfoValueSet(u8 *pos, u32 size);
|
void patchUnitInfoValueSet(u8 *pos, u32 size);
|
||||||
void reimplementSvcBackdoor(u8 *pos, u32 size);
|
void reimplementSvcBackdoor(u8 *pos, u32 size);
|
||||||
|
void implementSvcGetCFWInfo(u8 *pos, u32 size);
|
||||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
||||||
u8 *getUnitInfoValueSet(u8 *pos, u32 size);
|
u8 *getUnitInfoValueSet(u8 *pos, u32 size);
|
||||||
|
@ -131,12 +131,11 @@ void verifyPin(PINData *in)
|
|||||||
}
|
}
|
||||||
while(!(pressed & PIN_BUTTONS));
|
while(!(pressed & PIN_BUTTONS));
|
||||||
|
|
||||||
pressed &= PIN_BUTTONS & ~BUTTON_START;
|
|
||||||
|
|
||||||
if(!pressed) continue;
|
|
||||||
|
|
||||||
if(pressed & BUTTON_START) mcuPowerOff();
|
if(pressed & BUTTON_START) mcuPowerOff();
|
||||||
|
|
||||||
|
pressed &= PIN_BUTTONS & ~BUTTON_START;
|
||||||
|
if(!pressed) continue;
|
||||||
|
|
||||||
char key = PINKeyToLetter(pressed);
|
char key = PINKeyToLetter(pressed);
|
||||||
enteredPassword[cnt++] = (u8)key; // add character to password.
|
enteredPassword[cnt++] = (u8)key; // add character to password.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user