Move the kext outside Rosalina
- Stability (tm) - Boots 1s faster on N3DS - (∩ ͡° ͜ʖ ͡°)⊃━☆゚
This commit is contained in:
parent
ae8ea7da16
commit
e1d0602f25
14
Makefile
14
Makefile
@ -43,6 +43,7 @@ dir_arm11 := arm11
|
||||
dir_chainloader := chainloader
|
||||
dir_exceptions := exceptions
|
||||
dir_arm9_exceptions := $(dir_exceptions)/arm9
|
||||
dir_k11_extension := k11_extension
|
||||
dir_sysmodules := sysmodules
|
||||
dir_loader := $(dir_sysmodules)/loader
|
||||
dir_rosalina := $(dir_sysmodules)/rosalina
|
||||
@ -57,8 +58,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)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/mmuHook.bin.o $(dir_build)/k11MainHook.bin.o $(dir_build)/svcConnectToPortInitHook.bin.o $(dir_build)/svcCustomBackdoor.bin.o\
|
||||
$(dir_build)/chainloader.bin.o $(dir_build)/arm9_exceptions.bin.o
|
||||
bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/chainloader.bin.o $(dir_build)/arm9_exceptions.bin.o
|
||||
|
||||
modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi
|
||||
|
||||
@ -80,6 +80,7 @@ clean:
|
||||
@$(MAKE) -C $(dir_arm11) clean
|
||||
@$(MAKE) -C $(dir_chainloader) clean
|
||||
@$(MAKE) -C $(dir_arm9_exceptions) clean
|
||||
@$(MAKE) -C $(dir_k11_extension) clean
|
||||
@$(MAKE) -C $(dir_loader) clean
|
||||
@$(MAKE) -C $(dir_rosalina) clean
|
||||
@rm -rf $(dir_out) $(dir_build)
|
||||
@ -89,6 +90,7 @@ clean:
|
||||
.PHONY: $(dir_arm11)
|
||||
.PHONY: $(dir_chainloader)
|
||||
.PHONY: $(dir_arm9_exceptions)
|
||||
.PHONY: $(dir_k11_extension)
|
||||
.PHONY: $(dir_loader)
|
||||
.PHONY: $(dir_rosalina)
|
||||
|
||||
@ -96,9 +98,9 @@ $(dir_out)/$(name)$(revision).7z: all
|
||||
@mkdir -p "$(@D)"
|
||||
@7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser.py
|
||||
|
||||
$(dir_out)/boot.firm: $(dir_build)/modules.bin $(dir_build)/arm11.elf $(dir_build)/main.elf
|
||||
$(dir_out)/boot.firm: $(dir_build)/modules.bin $(dir_build)/arm11.elf $(dir_build)/main.elf $(dir_build)/k11_extension.bin
|
||||
@mkdir -p "$(@D)"
|
||||
@firmtool build $@ -D $^ -A 0x1FF60000 -C XDMA XDMA NDMA
|
||||
@firmtool build $@ -D $^ -A 0x1FF60000 0x18000000 -C XDMA XDMA NDMA XDMA
|
||||
|
||||
$(dir_build)/modules.bin: $(modules)
|
||||
@mkdir -p "$(@D)"
|
||||
@ -111,6 +113,10 @@ $(dir_build)/arm11.elf: $(dir_arm11)
|
||||
$(dir_build)/main.elf: $(bundled) $(objects)
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/k11_extension.bin: $(dir_k11_extension)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/loader.cxi: $(dir_loader)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
@ -6,7 +6,7 @@ endif
|
||||
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
name := kernel_extension
|
||||
name := k11_extension
|
||||
|
||||
dir_source := source
|
||||
dir_include := include
|
||||
@ -16,7 +16,7 @@ ARCH := -mcpu=mpcore -mfpu=vfp
|
||||
ASFLAGS := $(ARCH)
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -I$(dir_include) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math \
|
||||
-mword-relocations -ffunction-sections -fdata-sections
|
||||
LDFLAGS := -nostdlib -Wl,--gc-sections $(ARCH)
|
||||
LDFLAGS := -nostdlib -Wl,--gc-sections,--nmagic $(ARCH)
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
@ -76,8 +76,6 @@ extern bool (*kernelToUsrMemcpy8)(void *dst, const void *src, u32 len);
|
||||
extern bool (*kernelToUsrMemcpy32)(u32 *dst, const u32 *src, u32 len);
|
||||
extern s32 (*kernelToUsrStrncpy)(char *dst, const char *src, u32 len);
|
||||
|
||||
extern Result (*CustomBackdoor)(void *function, ...);
|
||||
|
||||
extern void (*svcFallbackHandler)(u8 svcId);
|
||||
extern void (*kernelpanic)(void);
|
||||
extern void (*PostprocessSvc)(void);
|
||||
@ -90,11 +88,16 @@ extern u32 *exceptionStackTop;
|
||||
extern u32 TTBCR;
|
||||
extern u32 L1MMUTableAddrs[4];
|
||||
|
||||
extern u32 kernelVersion;
|
||||
extern void *kernelUsrCopyFuncsStart, *kernelUsrCopyFuncsEnd;
|
||||
|
||||
extern bool *isDevUnit;
|
||||
|
||||
extern vu8 *configPage;
|
||||
extern u32 kernelVersion;
|
||||
extern u32 nbSection0Modules;
|
||||
|
||||
extern Result (*InterruptManager__MapInterrupt)(InterruptManager *manager, KBaseInterruptEvent *iEvent, u32 interruptID,
|
||||
u32 coreID, u32 priority, bool disableUponReceipt, bool levelHighActive);
|
||||
extern InterruptManager *interruptManager;
|
||||
extern KBaseInterruptEvent *customInterruptEvent;
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern u32 kernelVersion;
|
||||
|
||||
struct KMutex;
|
||||
struct KProcessO3DS;
|
||||
struct KProcessN3DS;
|
||||
@ -1124,7 +1126,6 @@ typedef union KCacheMaintenanceInterruptEvent
|
||||
extern bool isN3DS;
|
||||
extern void *officialSVCs[0x7E];
|
||||
|
||||
extern u32 kernelVersion;
|
||||
#define KPROCESS_OFFSETOF(field) (isN3DS ? offsetof(KProcessN3DS, field) :\
|
||||
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? offsetof(KProcessO3DS8x, field) :\
|
||||
offsetof(KProcessO3DSPre8x, field)))
|
33
k11_extension/include/svc/CustomBackdoor.h
Normal file
33
k11_extension/include/svc/CustomBackdoor.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 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 and 7.c of GPLv3 apply 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.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utils.h"
|
||||
#include "kernel.h"
|
||||
#include "svc.h"
|
||||
|
||||
void CustomBackdoor(void *function, ...);
|
19
k11_extension/linker.ld
Normal file
19
k11_extension/linker.ld
Normal file
@ -0,0 +1,19 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
|
||||
__start__ = .;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
|
||||
.bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; }
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
|
||||
__end__ = .;
|
||||
}
|
@ -35,7 +35,7 @@
|
||||
|
||||
bool isExceptionFatal(u32 spsr, u32 *regs, u32 index)
|
||||
{
|
||||
//if(CONFIG(DISABLEVECTORS)) return false;
|
||||
if(CONFIG(DISABLEVECTORS)) return false;
|
||||
|
||||
if((spsr & 0x1f) != 0x10) return true;
|
||||
|
@ -72,8 +72,6 @@ bool (*kernelToUsrMemcpy8)(void *dst, const void *src, u32 len);
|
||||
bool (*kernelToUsrMemcpy32)(u32 *dst, const u32 *src, u32 len);
|
||||
s32 (*kernelToUsrStrncpy)(char *dst, const char *src, u32 len);
|
||||
|
||||
Result (*CustomBackdoor)(void *function, ...);
|
||||
|
||||
void (*svcFallbackHandler)(u8 svcId);
|
||||
void (*kernelpanic)(void);
|
||||
void (*PostprocessSvc)(void);
|
||||
@ -86,11 +84,16 @@ u32 *exceptionStackTop;
|
||||
u32 TTBCR;
|
||||
u32 L1MMUTableAddrs[4];
|
||||
|
||||
u32 kernelVersion;
|
||||
void *kernelUsrCopyFuncsStart, *kernelUsrCopyFuncsEnd;
|
||||
|
||||
bool *isDevUnit;
|
||||
|
||||
vu8 *configPage;
|
||||
u32 kernelVersion;
|
||||
u32 nbSection0Modules;
|
||||
|
||||
Result (*InterruptManager__MapInterrupt)(InterruptManager *manager, KBaseInterruptEvent *iEvent, u32 interruptID,
|
||||
u32 coreID, u32 priority, bool disableUponReceipt, bool levelHighActive);
|
||||
InterruptManager *interruptManager;
|
||||
KBaseInterruptEvent *customInterruptEvent;
|
||||
|
@ -257,7 +257,7 @@ Result doPublishToProcessHook(Handle handle, u32 *cmdbuf)
|
||||
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
|
||||
}
|
||||
|
||||
if(terminateRosalina)
|
||||
if(terminateRosalina && nbSection0Modules == 6)
|
||||
{
|
||||
Handle rosalinaProcessHandle;
|
||||
res = OpenProcess(&rosalinaProcessHandle, 5);
|
@ -33,68 +33,87 @@
|
||||
#include "svcHandler.h"
|
||||
#include "memory.h"
|
||||
|
||||
static const u32 *const exceptionsPage = (const u32 *)0xFFFF0000;
|
||||
void *originalHandlers[8] = {NULL};
|
||||
|
||||
enum VECTORS { RESET = 0, UNDEFINED_INSTRUCTION, SVC, PREFETCH_ABORT, DATA_ABORT, RESERVED, IRQ, FIQ };
|
||||
extern u8 __start__[], __end__[], __bss_start__[], __bss_end__[];
|
||||
|
||||
static void setupSGI0Handler(void)
|
||||
struct KExtParameters
|
||||
{
|
||||
for(u32 i = 0; i < getNumberOfCores(); i++)
|
||||
interruptManager->N3DS.privateInterrupts[i][0].interruptEvent = customInterruptEvent;
|
||||
u32 ALIGN(0x400) L2MMUTableFor0x40000000[256];
|
||||
u32 basePA;
|
||||
void *originalHandlers[4];
|
||||
u32 L1MMUTableAddrs[4];
|
||||
|
||||
CfwInfo cfwInfo;
|
||||
} kExtParameters = { .basePA = 0x12345678 }; // place this in .data
|
||||
|
||||
void relocateAndSetupMMU(u32 coreId, u32 *L1Table)
|
||||
{
|
||||
struct KExtParameters *p0 = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + 0x18000000);
|
||||
struct KExtParameters *p = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + p0->basePA);
|
||||
|
||||
if(coreId == 0)
|
||||
{
|
||||
// Relocate ourselves, and clear BSS
|
||||
memcpy((void *)p0->basePA, (const void *)0x18000000, __bss_start__ - __start__);
|
||||
memset32((u32 *)(p0->basePA + (__bss_start__ - __start__)), 0, __bss_end__ - __bss_start__);
|
||||
|
||||
// Map the kernel ext to 0x40000000
|
||||
// 4KB extended small pages: [SYS:RW USR:-- X TYP:NORMAL SHARED OUTER NOCACHE, INNER CACHED WB WA]
|
||||
for(u32 offset = 0; offset < (u32)(__end__ - __start__); offset += 0x1000)
|
||||
p->L2MMUTableFor0x40000000[offset >> 12] = (p0->basePA + offset) | 0x516;
|
||||
|
||||
__asm__ __volatile__ ("sev");
|
||||
}
|
||||
else
|
||||
__asm__ __volatile__ ("wfe");
|
||||
|
||||
// bit31 idea thanks to SALT
|
||||
// Maps physmem so that, if addr is in physmem(0, 0x30000000), it can be accessed uncached&rwx as addr|(1<<31)
|
||||
u32 attribs = 0x40C02; // supersection (rwx for all) of strongly ordered memory, shared
|
||||
for(u32 PA = 0; PA < 0x30000000; PA += 0x01000000)
|
||||
{
|
||||
u32 VA = (1 << 31) | PA;
|
||||
for(u32 i = 0; i < 16; i++)
|
||||
L1Table[i + (VA >> 20)] = PA | attribs;
|
||||
}
|
||||
|
||||
static inline void **getHandlerDestination(enum VECTORS vector)
|
||||
{
|
||||
u32 *branch_dst = (u32 *)decodeARMBranch((u32 *)exceptionsPage + (u32)vector);
|
||||
return (void **)(branch_dst + 2);
|
||||
L1Table[0x40000000 >> 20] = (u32)p->L2MMUTableFor0x40000000 | 1;
|
||||
|
||||
p->L1MMUTableAddrs[coreId] = (u32)L1Table;
|
||||
}
|
||||
|
||||
static inline void swapHandlerInVeneer(enum VECTORS vector, void *handler)
|
||||
void bindSGI0Hook(void)
|
||||
{
|
||||
void **dst = getHandlerDestination(vector);
|
||||
originalHandlers[(u32)vector] = *dst;
|
||||
if(handler != NULL)
|
||||
*(void**)PA_FROM_VA_PTR(dst) = handler;
|
||||
if(InterruptManager__MapInterrupt(interruptManager, customInterruptEvent, 0, getCurrentCoreID(), 0, false, false) != 0)
|
||||
__asm__ __volatile__ ("bkpt 0xdead");
|
||||
}
|
||||
|
||||
static bool **enableUserExceptionHandlersForCPUExcLoc;
|
||||
static bool enableUserExceptionHandlersForCPUExc = true;
|
||||
|
||||
static void setupSvcHandler(void)
|
||||
void configHook(vu8 *cfgPage)
|
||||
{
|
||||
swapHandlerInVeneer(SVC, svcHandler);
|
||||
configPage = cfgPage;
|
||||
|
||||
void **arm11SvcTable = (void**)originalHandlers[(u32)SVC];
|
||||
while(*arm11SvcTable != NULL) arm11SvcTable++; //Look for SVC0 (NULL)
|
||||
memcpy(officialSVCs, arm11SvcTable, 4 * 0x7E);
|
||||
|
||||
officialSVCs[0x2D] = *((void **)officialSVCs[0x2D] + 1);
|
||||
|
||||
CustomBackdoor = (Result (*)(void *, ...))((u32 *)officialSVCs[0x2F] + 2);
|
||||
officialSVCs[0x2F] = *((void **)officialSVCs[0x2F] + 1);
|
||||
|
||||
u32 *off = (u32 *)originalHandlers[(u32) SVC];
|
||||
while(*off++ != 0xE1A00009);
|
||||
svcFallbackHandler = (void (*)(u8))decodeARMBranch(off);
|
||||
for(; *off != 0xE92D000F; off++);
|
||||
PostprocessSvc = (void (*)(void))decodeARMBranch(off + 1);
|
||||
}
|
||||
|
||||
static void setupExceptionHandlers(void)
|
||||
{
|
||||
swapHandlerInVeneer(FIQ, FIQHandler);
|
||||
swapHandlerInVeneer(UNDEFINED_INSTRUCTION, undefinedInstructionHandler);
|
||||
swapHandlerInVeneer(PREFETCH_ABORT, prefetchAbortHandler);
|
||||
swapHandlerInVeneer(DATA_ABORT, dataAbortHandler);
|
||||
|
||||
setupSvcHandler();
|
||||
kernelVersion = *(vu32 *)configPage;
|
||||
*isDevUnit = true; // enable debug features
|
||||
}
|
||||
|
||||
static void findUsefulSymbols(void)
|
||||
{
|
||||
u32 *off;
|
||||
|
||||
for(off = (u32 *)0xFFFF0000; *off != 0xE1A0D002; off++);
|
||||
off += 3;
|
||||
initFPU = (void (*) (void))off;
|
||||
|
||||
for(; *off != 0xE3A0A0C2; off++);
|
||||
mcuReboot = (void (*) (void))--off;
|
||||
coreBarrier = (void (*) (void))decodeARMBranch(off - 4);
|
||||
|
||||
for(off = (u32 *)originalHandlers[2]; *off != 0xE1A00009; off++);
|
||||
svcFallbackHandler = (void (*)(u8))decodeARMBranch(off + 1);
|
||||
for(; *off != 0xE92D000F; off++);
|
||||
PostprocessSvc = (void (*)(void))decodeARMBranch(off + 1);
|
||||
|
||||
KProcessHandleTable__ToKProcess = (KProcess * (*)(KProcessHandleTable *, Handle))decodeARMBranch(5 + (u32 *)officialSVCs[0x76]);
|
||||
|
||||
for(off = (u32 *)KProcessHandleTable__ToKProcess; *off != 0xE28DD014; off++);
|
||||
@ -131,6 +150,9 @@ static void findUsefulSymbols(void)
|
||||
|
||||
KProcessHandleTable__ToKThread = (KThread * (*)(KProcessHandleTable *, Handle))decodeARMBranch((u32 *)decodeARMBranch((u32 *)officialSVCs[0x37] + 3) /* GetThreadId */ + 5);
|
||||
|
||||
for(off = (u32 *)officialSVCs[0x50]; off[0] != 0xE1A05000 || off[1] != 0xE2100102 || off[2] != 0x5A00000B; off++);
|
||||
InterruptManager__MapInterrupt = (Result (*)(InterruptManager *, KBaseInterruptEvent *, u32, u32, u32, bool, bool))decodeARMBranch(--off);
|
||||
interruptManager = *(InterruptManager **)(off - 4 + (off[-6] & 0xFFF) / 4);
|
||||
for(off = (u32 *)officialSVCs[0x54]; *off != 0xE8BD8008; off++);
|
||||
flushDataCacheRange = (void (*)(void *, u32))(*(u32 **)(off[1]) + 3);
|
||||
|
||||
@ -145,7 +167,7 @@ static void findUsefulSymbols(void)
|
||||
for(; *off != 0xE320F000; off++);
|
||||
KObjectMutex__ErrorOccured = (void (*)(void))decodeARMBranch(off + 1);
|
||||
|
||||
for(off = (u32 *)originalHandlers[(u32) DATA_ABORT]; *off != (u32)exceptionStackTop; off++);
|
||||
for(off = (u32 *)originalHandlers[4]; *off != (u32)exceptionStackTop; off++);
|
||||
kernelUsrCopyFuncsStart = (void *)off[1];
|
||||
kernelUsrCopyFuncsEnd = (void *)off[2];
|
||||
|
||||
@ -202,16 +224,14 @@ static void findUsefulSymbols(void)
|
||||
for(off = (u32 *)0xFFFF0000; off[0] != 0xE3A01002 || off[1] != 0xE3A00004; off++);
|
||||
SignalDebugEvent = (Result (*)(DebugEventType type, u32 info, ...))decodeARMBranch(off + 2);
|
||||
|
||||
for(off = (u32 *)PA_FROM_VA_PTR(off); *off != 0x96007F9; off++);
|
||||
for(; *off != 0x96007F9; off++);
|
||||
isDevUnit = *(bool **)(off - 1);
|
||||
enableUserExceptionHandlersForCPUExcLoc = (bool **)(off + 1);
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Shitty/lazy heuristic but it works on even 4.5, so...
|
||||
u32 textStart = ((u32)originalHandlers[(u32) SVC]) & ~0xFFFF;
|
||||
u32 rodataStart = (u32)(interruptManager->N3DS.privateInterrupts[0][6].interruptEvent->vtable) & ~0xFFF;
|
||||
|
||||
u32 textStart = ((u32)originalHandlers[2]) & ~0xFFFF;
|
||||
u32 rodataStart = (u32)(interruptManager->N3DS.privateInterrupts[1][0x1D].interruptEvent->vtable) & ~0xFFF;
|
||||
u32 textSize = rodataStart - textStart;
|
||||
for(off = (u32 *)textStart; off < (u32 *)(textStart + textSize - 12); off++)
|
||||
{
|
||||
@ -228,76 +248,28 @@ static void findUsefulSymbols(void)
|
||||
}
|
||||
}
|
||||
|
||||
struct Parameters
|
||||
void main(void)
|
||||
{
|
||||
void (*SGI0HandlerCallback)(struct Parameters *, u32 *);
|
||||
InterruptManager *interruptManager;
|
||||
u32 *L2MMUTable; // bit31 mapping
|
||||
struct KExtParameters *p = &kExtParameters;
|
||||
u32 TTBCR_;
|
||||
s64 nb;
|
||||
|
||||
void (*initFPU)(void);
|
||||
void (*mcuReboot)(void);
|
||||
void (*coreBarrier)(void);
|
||||
|
||||
u32 TTBCR;
|
||||
u32 L1MMUTableAddrs[4];
|
||||
|
||||
u32 kernelVersion;
|
||||
|
||||
CfwInfo cfwInfo;
|
||||
};
|
||||
|
||||
static void enableDebugFeatures(void)
|
||||
{
|
||||
*isDevUnit = true; // for debug SVCs and user exc. handlers, etc.
|
||||
*enableUserExceptionHandlersForCPUExcLoc = &enableUserExceptionHandlersForCPUExc;
|
||||
|
||||
u32 *off;
|
||||
for(off = (u32 *)PA_FROM_VA_PTR(KernelSetState); off[0] != 0xE5D00001 || off[1] != 0xE3500000; off++);
|
||||
off[2] = 0xE1A00000; // in case 6: beq -> nop
|
||||
|
||||
for(off = (u32 *)PA_FROM_VA_PTR(DebugActiveProcess); *off != 0xE3110001; off++);
|
||||
*off = 0xE3B01001; // tst r1, #1 -> movs r1, #1
|
||||
}
|
||||
|
||||
static void doOtherPatches(void)
|
||||
{
|
||||
u32 *kpanic = (u32 *)kernelpanic;
|
||||
*(u32 *)PA_FROM_VA_PTR(kpanic) = 0xE12FFF7E; // bkpt 0xFFFE
|
||||
|
||||
u32 *off;
|
||||
for(off = (u32 *)PA_FROM_VA_PTR(ControlMemory); (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++);
|
||||
off -= 2;
|
||||
|
||||
/*
|
||||
Here we replace currentProcess->processID == 1 by additionnalParameter == 1.
|
||||
This patch should be generic enough to work even on firmware version 5.0.
|
||||
|
||||
It effectively changes the prototype of the ControlMemory function which
|
||||
only caller is the svc 0x01 handler on OFW.
|
||||
*/
|
||||
*(u32 *)PA_FROM_VA_PTR(off) = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeARMFrameSize((u32 *)PA_FROM_VA_PTR(ControlMemory))); // ldr r0, [sp, #(frameSize + 8)]
|
||||
}
|
||||
|
||||
void main(volatile struct Parameters *p)
|
||||
{
|
||||
__asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(TTBCR_));
|
||||
TTBCR = TTBCR_;
|
||||
isN3DS = getNumberOfCores() == 4;
|
||||
interruptManager = p->interruptManager;
|
||||
|
||||
initFPU = p->initFPU;
|
||||
mcuReboot = p->mcuReboot;
|
||||
coreBarrier = p->coreBarrier;
|
||||
|
||||
TTBCR = p->TTBCR;
|
||||
memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16);
|
||||
exceptionStackTop = (u32 *)0xFFFF2000 + (1 << (32 - TTBCR - 20));
|
||||
kernelVersion = p->kernelVersion;
|
||||
cfwInfo = p->cfwInfo;
|
||||
|
||||
setupSGI0Handler();
|
||||
setupExceptionHandlers();
|
||||
memcpy(originalHandlers + 1, p->originalHandlers, 16);
|
||||
void **arm11SvcTable = (void**)originalHandlers[2];
|
||||
while(*arm11SvcTable != NULL) arm11SvcTable++; //Look for SVC0 (NULL)
|
||||
memcpy(officialSVCs, arm11SvcTable, 4 * 0x7E);
|
||||
|
||||
findUsefulSymbols();
|
||||
enableDebugFeatures();
|
||||
doOtherPatches();
|
||||
|
||||
GetSystemInfo(&nb, 26, 0);
|
||||
nbSection0Modules = (u32)nb;
|
||||
|
||||
rosalinaState = 0;
|
||||
hasStartedRosalinaNetworkFuncsOnce = false;
|
@ -22,40 +22,57 @@
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.text
|
||||
.arm
|
||||
.section .text.start
|
||||
.balign 4
|
||||
.global _start
|
||||
_start:
|
||||
b start
|
||||
b startPhys
|
||||
|
||||
.global svc0x2F
|
||||
.type svc0x2F, %function
|
||||
svc0x2F:
|
||||
@ custom backdoor before kernel ext. is installed
|
||||
svc 0x2F
|
||||
b _bindSGI0Hook
|
||||
b configHook
|
||||
|
||||
b undefinedInstructionHandler
|
||||
b svcHandler
|
||||
b prefetchAbortHandler
|
||||
b dataAbortHandler
|
||||
|
||||
.word __end__
|
||||
.word kExtParameters
|
||||
.word 1 @ enableUserExceptionHandlersForCPUExc
|
||||
|
||||
start:
|
||||
@ Only core0 executes this, the other cores are running coreBarrier
|
||||
|
||||
@ Skipped instruction:
|
||||
str r1, [r4, #0x8]
|
||||
|
||||
push {r0-r12, lr}
|
||||
|
||||
@ Adjust the size of the SYSTEM memregion
|
||||
sub r4, #8
|
||||
ldr r0, [r4, #0xC]
|
||||
ldr r1, =__end__
|
||||
ldr r2, =__start__
|
||||
sub r1, r2
|
||||
sub r0, r1
|
||||
str r0, [r4, #0xC]
|
||||
|
||||
bl main
|
||||
|
||||
pop {r0-r12, pc}
|
||||
|
||||
startPhys:
|
||||
push {r0-r12, lr}
|
||||
mrc p15, 0, r0, c0, c0, 5 @ CPUID register
|
||||
and r0, #3
|
||||
mov r1, r2
|
||||
bl relocateAndSetupMMU
|
||||
pop {r0-r12, lr}
|
||||
mov r12, #0x20000000 @ instruction that has been patched
|
||||
bx lr
|
||||
|
||||
.global convertVAToPA
|
||||
.type convertVAToPA, %function
|
||||
convertVAToPA:
|
||||
@ needs to be executed in supervisor mode
|
||||
mov r1, #0x1000
|
||||
sub r1, #1
|
||||
and r2, r0, r1
|
||||
bic r0, r1
|
||||
mcr p15, 0, r0, c7, c8, 0 @ VA to PA translation with privileged read permission check
|
||||
mrc p15, 0, r0, c7, c4, 0 @ read PA register
|
||||
tst r0, #1 @ failure bit
|
||||
bic r0, r1
|
||||
addeq r0, r2
|
||||
movne r0, #0
|
||||
bx lr
|
||||
|
||||
.section .data
|
||||
|
||||
.p2align 12
|
||||
.global kernel_extension
|
||||
kernel_extension: .incbin "build/kernel_extension.bin"
|
||||
.p2align 12
|
||||
kernel_extension_end:
|
||||
|
||||
.global kernel_extension_size
|
||||
kernel_extension_size: .word kernel_extension_end - kernel_extension
|
||||
_bindSGI0Hook:
|
||||
push {r0-r12, lr}
|
||||
bl bindSGI0Hook
|
||||
pop {r0-r12, pc}
|
@ -37,6 +37,7 @@
|
||||
#include "svc/SetWifiEnabled.h"
|
||||
#include "svc/Backdoor.h"
|
||||
#include "svc/KernelSetState.h"
|
||||
#include "svc/CustomBackdoor.h"
|
||||
#include "svc/MapProcessMemoryEx.h"
|
||||
#include "svc/UnmapProcessMemoryEx.h"
|
||||
#include "svc/ControlService.h"
|
||||
@ -51,7 +52,7 @@ static inline void yieldDuringRosalinaMenu(void)
|
||||
|
||||
u64 titleId = codeSetOfProcess(currentProcess)->titleId;
|
||||
u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)titleId;
|
||||
while((rosalinaState & 1) && idOfProcess(currentProcess) >= 6 &&
|
||||
while((rosalinaState & 1) && idOfProcess(currentProcess) >= nbSection0Modules &&
|
||||
(highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))))
|
||||
SleepThread(25 * 1000 * 1000LL);
|
||||
}
|
@ -22,38 +22,17 @@
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.section .text.start
|
||||
.text
|
||||
.arm
|
||||
.balign 4
|
||||
.global _start
|
||||
_start:
|
||||
b start
|
||||
b ConnectToPortHookWrapper
|
||||
|
||||
start:
|
||||
.global CustomBackdoor
|
||||
.type CustomBackdoor, %function
|
||||
CustomBackdoor:
|
||||
push {r4, lr}
|
||||
|
||||
mrc p15, 0, r4, c0, c0, 5 @ CPUID register
|
||||
and r4, #3
|
||||
cmp r4, #1
|
||||
beq _core1_only
|
||||
|
||||
_waitLoop:
|
||||
wfe
|
||||
ldr r0, =_setupFinished
|
||||
ldr r0, [r0]
|
||||
cmp r0, #0
|
||||
beq _waitLoop
|
||||
b end
|
||||
|
||||
_core1_only:
|
||||
bl main
|
||||
ldr r0, =_setupFinished
|
||||
str r4, [r0]
|
||||
sev
|
||||
|
||||
end:
|
||||
mov r4, r0
|
||||
mov r0, r1
|
||||
mov r1, r2
|
||||
mov r2, r3
|
||||
blx r4
|
||||
pop {r4, pc}
|
||||
|
||||
.bss
|
||||
.balign 4
|
||||
_setupFinished: .word 0
|
@ -1,66 +0,0 @@
|
||||
.arm.little
|
||||
|
||||
.create "build/k11MainHook.bin", 0
|
||||
.arm
|
||||
|
||||
bindSGI0:
|
||||
; hook __kernel_main to bind SGI0 for own purposes
|
||||
push {r0-r4, lr}
|
||||
sub sp, #16 ; 3 args passed through the stack + alignment
|
||||
adr r0, parameters
|
||||
ldr r0, [r0, #4]
|
||||
adr r1, interruptEvent
|
||||
mov r2, #0
|
||||
mrc p15, 0, r3, c0, c0, 5
|
||||
and r3, #3
|
||||
mov r4, #0
|
||||
str r4, [sp]
|
||||
str r4, [sp, #4]
|
||||
str r4, [sp, #8]
|
||||
|
||||
ldr r12, [InterruptManager_MapInterrupt]
|
||||
blx r12
|
||||
cmp r0, #0
|
||||
blt .
|
||||
|
||||
add sp, #16
|
||||
pop {r0-r4, pc}
|
||||
|
||||
executeCustomHandler:
|
||||
push {r4, lr}
|
||||
mrs r4, cpsr
|
||||
adr r0, parameters
|
||||
bl convertVAToPA
|
||||
orr r0, #(1 << 31)
|
||||
ldr r12, [r0]
|
||||
|
||||
blx r12
|
||||
|
||||
mov r0, #0
|
||||
msr cpsr_cx, r4
|
||||
pop {r4, pc}
|
||||
|
||||
convertVAToPA:
|
||||
mov r1, #0x1000
|
||||
sub r1, #1
|
||||
and r2, r0, r1
|
||||
bic r0, r1
|
||||
mcr p15, 0, r0, c7, c8, 0 ; VA to PA translation with privileged read permission check
|
||||
mrc p15, 0, r0, c7, c4, 0 ; read PA register
|
||||
tst r0, #1 ; failure bit
|
||||
bic r0, r1
|
||||
addeq r0, r2
|
||||
movne r0, #0
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
|
||||
; Result InterruptManager::MapInterrupt(InterruptManager *this, InterruptEvent *iEvent, u32 interruptID, u32 coreID, s32 priority, bool willBeMasked, bool isLevelHighActive);
|
||||
InterruptManager_MapInterrupt: .ascii "bind"
|
||||
|
||||
_vtable: .word executeCustomHandler
|
||||
interruptEvent: .word _vtable
|
||||
|
||||
parameters:
|
||||
|
||||
.close
|
@ -1,36 +0,0 @@
|
||||
.arm.little
|
||||
|
||||
.create "build/mmuHook.bin", 0
|
||||
.arm
|
||||
; r2 = L1 table
|
||||
; Thanks @Dazzozo for giving me that idea
|
||||
; Maps physmem so that, if addr is in physmem(0, 0x30000000), it can be accessed uncached&rwx as addr|(1<<31)
|
||||
; Save the value of all registers
|
||||
|
||||
push {r0-r1, r3-r7}
|
||||
mov r0, #0
|
||||
mov r1, #0x30000000 ; end address
|
||||
ldr r3, =#0x40C02 ; supersection (rwx for all) of strongly ordered memory, shared
|
||||
loop:
|
||||
orr r4, r0, #0x80000000
|
||||
orr r5, r0, r3
|
||||
|
||||
mov r6, #0 ;
|
||||
loop2:
|
||||
add r7, r6, r4,lsr #20
|
||||
str r5, [r2, r7,lsl #2]
|
||||
add r6, #1
|
||||
cmp r6, #16
|
||||
blo loop2
|
||||
|
||||
add r0, #0x01000000
|
||||
cmp r0, r1
|
||||
blo loop
|
||||
pop {r0-r1, r3-r7}
|
||||
|
||||
mov r3, #0xe0000000 ; instruction that has been patched
|
||||
bx lr
|
||||
|
||||
|
||||
.pool
|
||||
.close
|
@ -1,32 +0,0 @@
|
||||
.arm.little
|
||||
|
||||
.create "build/svcConnectToPortInitHook.bin", 0
|
||||
.arm
|
||||
b skip_vars
|
||||
vars:
|
||||
orig: .word 0
|
||||
SleepThread: .word 0
|
||||
skip_vars:
|
||||
push {r0-r4, lr}
|
||||
ldr r4, =0x1ff81108
|
||||
|
||||
loop:
|
||||
ldrb r12, [r4]
|
||||
cmp r12, #0
|
||||
bne loop_end
|
||||
|
||||
ldr r12, [SleepThread]
|
||||
ldr r0, =(10 * 1000 * 1000)
|
||||
mov r1, #0
|
||||
blx r12
|
||||
b loop
|
||||
|
||||
loop_end:
|
||||
pop {r0-r4, lr}
|
||||
mov r12, #0x40000000
|
||||
add r12, #4
|
||||
bx r12
|
||||
|
||||
.pool
|
||||
|
||||
.close
|
@ -1,20 +0,0 @@
|
||||
.arm.little
|
||||
|
||||
.create "build/svcCustomBackdoor.bin", 0
|
||||
.arm
|
||||
|
||||
; Result svcCustomBackdoor(void *func, ... <up to 3 args>)
|
||||
svcCustomBackdoor:
|
||||
b skip_orig
|
||||
orig: .word 0
|
||||
skip_orig:
|
||||
push {r4, lr}
|
||||
mov r4, r0
|
||||
mov r0, r1
|
||||
mov r1, r2
|
||||
mov r2, r3
|
||||
blx r4
|
||||
pop {r4, pc}
|
||||
|
||||
.pool
|
||||
.close
|
@ -28,9 +28,6 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
|
||||
#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
|
||||
|
||||
void installArm9Handlers(void);
|
||||
u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset, u32 *dAbtHandler, u32 dAbtHandlerMemAddress);
|
||||
void detectAndProcessExceptionDumps(void);
|
||||
|
@ -227,10 +227,8 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
||||
u32 kernel9Size = (u32)(process9Offset - arm9Section) - sizeof(Cxi) - 0x200,
|
||||
ret = 0;
|
||||
|
||||
installMMUHook(arm11Section1, firm->section[1].size, &freeK11Space);
|
||||
installK11MainHook(arm11Section1, firm->section[1].size, isSafeMode, baseK11VA, arm11SvcTable, arm11ExceptionsPage, &freeK11Space);
|
||||
installSvcConnectToPortInitHook(arm11SvcTable, arm11ExceptionsPage, &freeK11Space);
|
||||
installSvcCustomBackdoor(arm11SvcTable, &freeK11Space, arm11ExceptionsPage);
|
||||
ret += installK11Extension(arm11Section1, firm->section[1].size, isSafeMode, baseK11VA, arm11ExceptionsPage, &freeK11Space);
|
||||
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
|
||||
|
||||
//Apply signature patches
|
||||
ret += patchSignatureChecks(process9Offset, process9Size);
|
||||
@ -276,6 +274,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
||||
mergeSection0(NATIVE_FIRM, loadFromStorage);
|
||||
firm->section[0].size = 0;
|
||||
|
||||
fileWrite(arm11Section1, "/luma/testsection1.bin", firm->section[1].size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
167
source/patches.c
167
source/patches.c
@ -78,37 +78,39 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 *
|
||||
return arm11SvcTable;
|
||||
}
|
||||
|
||||
void installMMUHook(u8 *pos, u32 size, u8 **freeK11Space)
|
||||
// For ARM prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases)
|
||||
static inline u32 computeARMFrameSize(const u32 *prolog)
|
||||
{
|
||||
static const u8 pattern[] = {0x0E, 0x32, 0xA0, 0xE3, 0x02, 0xC2, 0xA0, 0xE3};
|
||||
const u32 *off;
|
||||
|
||||
u32 *off = (u32 *)memsearch(pos, pattern, size, 8);
|
||||
for(off = prolog; (*off >> 16) != 0xE92D; off++); // look for stmfd sp! = push
|
||||
u32 nbPushedRegs = 0;
|
||||
for(u32 val = *off & 0xFFFF; val != 0; val >>= 1) // 1 bit = 1 pushed register
|
||||
nbPushedRegs += val & 1;
|
||||
for(; (*off >> 8) != 0xE24DD0; off++); // look for sub sp, #offset
|
||||
u32 localVariablesSpaceSize = *off & 0xFF;
|
||||
|
||||
memcpy(*freeK11Space, mmuHook_bin, mmuHook_bin_size);
|
||||
*off = MAKE_BRANCH_LINK(off, *freeK11Space);
|
||||
|
||||
(*freeK11Space) += mmuHook_bin_size;
|
||||
return 4 * nbPushedRegs + localVariablesSpaceSize;
|
||||
}
|
||||
|
||||
void installK11MainHook(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage, u8 **freeK11Space)
|
||||
static inline u32 *getKernel11HandlerVAPos(u8 *pos, u32 *arm11ExceptionsPage, u32 baseK11VA, u32 id)
|
||||
{
|
||||
u32 off = ((-((arm11ExceptionsPage[id] & 0xFFFFFF) << 2)) & (0xFFFFFF << 2)) - 8;
|
||||
u32 pointedInstructionVA = 0xFFFF0000 + 4 * id - off;
|
||||
return (u32 *)(pos + pointedInstructionVA - baseK11VA + 8);
|
||||
}
|
||||
|
||||
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space)
|
||||
{
|
||||
//The parameters to be passed on to the kernel ext
|
||||
//Please keep that in sync with the definition in kernel_extension_setup.c and kernel_extension/main.c
|
||||
//Please keep that in sync with the definition in k11_extension/source/main.c
|
||||
struct KExtParameters
|
||||
{
|
||||
void (*SGI0HandlerCallback)(struct KExtParameters *, u32 *);
|
||||
void *interruptManager;
|
||||
u32 *L2MMUTable; //bit31 mapping
|
||||
|
||||
void (*initFPU)(void);
|
||||
void (*mcuReboot)(void);
|
||||
void (*coreBarrier)(void);
|
||||
|
||||
u32 TTBCR;
|
||||
u32 __attribute__((aligned(0x400))) L2MMUTableFor0x40000000[256];
|
||||
u32 basePA;
|
||||
void *originalHandlers[4];
|
||||
u32 L1MMUTableAddrs[4];
|
||||
|
||||
u32 kernelVersion;
|
||||
|
||||
struct CfwInfo
|
||||
{
|
||||
char magic[4];
|
||||
@ -124,42 +126,61 @@ void installK11MainHook(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
||||
} __attribute__((packed)) info;
|
||||
};
|
||||
|
||||
static const u8 pattern[] = {0x00, 0x00, 0xA0, 0xE1, 0x03, 0xF0, 0x20, 0xE3, 0xFD, 0xFF, 0xFF, 0xEA};
|
||||
static const u8 patternHook1[] = {0x02, 0xC2, 0xA0, 0xE3, 0xFF}; //MMU setup hook
|
||||
static const u8 patternHook2[] = {0x08, 0x00, 0xA4, 0xE5, 0x02, 0x10, 0x80, 0xE0, 0x08, 0x10, 0x84, 0xE5}; //FCRAM layout setup hook
|
||||
static const u8 patternHook3_4[] = {0x00, 0x00, 0xA0, 0xE1, 0x03, 0xF0, 0x20, 0xE3, 0xFD, 0xFF, 0xFF, 0xEA}; //SGI0 setup code, etc.
|
||||
|
||||
u32 *off = (u32 *)memsearch(pos, pattern, size, 12);
|
||||
//look for cpsie i and place our function call in the nop 2 instructions before
|
||||
while(*off != 0xF1080080) off--;
|
||||
off -= 2;
|
||||
|
||||
memcpy(*freeK11Space, k11MainHook_bin, k11MainHook_bin_size);
|
||||
//Our kernel11 extension is initially loaded in VRAM
|
||||
u32 kextTotalSize = *(u32 *)0x18000020 - 0x40000000;
|
||||
u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - kextTotalSize;
|
||||
|
||||
u32 *hookVeneers = (u32 *)*freeK11Space;
|
||||
u32 relocBase = 0xFFFF0000 + (*freeK11Space - (u8 *)arm11ExceptionsPage);
|
||||
*off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase);
|
||||
|
||||
off = (u32 *)(pos + (arm11SvcTable[0x50] - baseK11VA)); //svcBindInterrupt
|
||||
while(off[0] != 0xE1A05000 || off[1] != 0xE2100102 || off[2] != 0x5A00000B) off++;
|
||||
off--;
|
||||
hookVeneers[0] = 0xE51FF004; //ldr pc, [pc, #-8+4]
|
||||
hookVeneers[1] = 0x18000004;
|
||||
hookVeneers[2] = 0xE51FF004;
|
||||
hookVeneers[3] = 0x40000000;
|
||||
hookVeneers[4] = 0xE51FF004;
|
||||
hookVeneers[5] = 0x40000008;
|
||||
hookVeneers[6] = 0xE51FF004;
|
||||
hookVeneers[7] = 0x4000000C;
|
||||
|
||||
signed int offset = (*off & 0xFFFFFF) << 2;
|
||||
offset = offset << 6 >> 6; //sign extend
|
||||
offset += 8;
|
||||
(*freeK11Space) += 32;
|
||||
|
||||
u32 InterruptManager_MapInterrupt = baseK11VA + ((u8 *)off - pos) + offset;
|
||||
u32 interruptManager = *(u32 *)(off - 4 + (*(off - 6) & 0xFFF) / 4);
|
||||
//MMU setup hook
|
||||
u32 *off = (u32 *)memsearch(pos, patternHook1, size, sizeof(patternHook1));
|
||||
if(off == NULL) return 1;
|
||||
*off = MAKE_BRANCH_LINK(off, hookVeneers);
|
||||
|
||||
off = (u32 *)memsearch(*freeK11Space, "bind", k11MainHook_bin_size, 4);
|
||||
//Most important hook: FCRAM layout setup hook
|
||||
off = (u32 *)memsearch(pos, patternHook2, size, sizeof(patternHook2));
|
||||
if(off == NULL) return 1;
|
||||
off += 2;
|
||||
*off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase + 8);
|
||||
|
||||
off[0] = InterruptManager_MapInterrupt;
|
||||
//Bind SGI0 hook
|
||||
//Look for cpsie i and place our hook in the nop 2 instructions before
|
||||
off = (u32 *)memsearch(pos, patternHook3_4, size, 12);
|
||||
if(off == NULL) return 1;
|
||||
for(; *off != 0xF1080080; off--);
|
||||
off -= 2;
|
||||
*off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase + 16);
|
||||
|
||||
//Relocate stuff
|
||||
off[1] += relocBase;
|
||||
off[2] += relocBase;
|
||||
//Config hook (after the configuration memory fields have been filled)
|
||||
for(; *off != 0xE1A00000; off++);
|
||||
off += 4;
|
||||
*off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase + 24);
|
||||
|
||||
struct KExtParameters *p = (struct KExtParameters *)(off + 3);
|
||||
memset(p, 0, sizeof(struct KExtParameters));
|
||||
memcpy((void *)&p->SGI0HandlerCallback, "hdlr", 4);
|
||||
struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - 0x40000000 + 0x18000000);
|
||||
p->basePA = dstKextPA;
|
||||
|
||||
p->interruptManager = (void *)interruptManager;
|
||||
for(u32 i = 0; i < 4; i++)
|
||||
{
|
||||
u32 *handlerPos = getKernel11HandlerVAPos(pos, arm11ExceptionsPage, baseK11VA, 1 + i);
|
||||
p->originalHandlers[i] = (void *)*handlerPos;
|
||||
*handlerPos = 0x40000010 + 4 * i;
|
||||
}
|
||||
|
||||
struct CfwInfo *info = &p->info;
|
||||
memcpy(&info->magic, "LUMA", 4);
|
||||
@ -174,32 +195,52 @@ void installK11MainHook(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
||||
if(isSafeMode) info->flags |= 1 << 5;
|
||||
if(isSdMode) info->flags |= 1 << 6;
|
||||
|
||||
(*freeK11Space) += (k11MainHook_bin_size + sizeof(struct KExtParameters));
|
||||
(*freeK11Space) += 4 - ((u32)(*freeK11Space) % 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void installSvcConnectToPortInitHook(u32 *arm11SvcTable, u32 *arm11ExceptionsPage, u8 **freeK11Space)
|
||||
u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage)
|
||||
{
|
||||
u32 addr = 0xFFFF0000 + (u32)*freeK11Space - (u32)arm11ExceptionsPage;
|
||||
u32 svcSleepThreadAddr = arm11SvcTable[0x0A], svcConnectToPortAddr = arm11SvcTable[0x2D];
|
||||
static const u8 patternKPanic[] = {0x02, 0x0B, 0x44, 0xE2};
|
||||
|
||||
arm11SvcTable[0x2D] = addr;
|
||||
memcpy(*freeK11Space, svcConnectToPortInitHook_bin, svcConnectToPortInitHook_bin_size);
|
||||
//Assumption: ControlMemory, DebugActiveProcess and KernelSetState are in the first 0x20000 bytes
|
||||
//Patch ControlMemory
|
||||
u8 *instrPos = pos + (arm11SvcTable[1] + 20 - baseK11VA);
|
||||
s32 displ = (*(u32 *)instrPos & 0xFFFFFF) << 2;
|
||||
displ = (displ << 6) >> 6; // sign extend
|
||||
|
||||
u32 *off = (u32 *)(*freeK11Space);
|
||||
off[1] = svcConnectToPortAddr;
|
||||
off[2] = svcSleepThreadAddr;
|
||||
u8 *ControlMemoryPos = instrPos + 8 + displ;
|
||||
u32 *off;
|
||||
|
||||
(*freeK11Space) += svcConnectToPortInitHook_bin_size;
|
||||
}
|
||||
/*
|
||||
Here we replace currentProcess->processID == 1 by additionnalParameter == 1.
|
||||
This patch should be generic enough to work even on firmware version 5.0.
|
||||
|
||||
It effectively changes the prototype of the ControlMemory function which
|
||||
only caller is the svc 0x01 handler on OFW.
|
||||
*/
|
||||
for(off = (u32 *)ControlMemoryPos; (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++);
|
||||
off -= 2;
|
||||
*off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeARMFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)]
|
||||
|
||||
void installSvcCustomBackdoor(u32 *arm11SvcTable, u8 **freeK11Space, u32 *arm11ExceptionsPage)
|
||||
{
|
||||
memcpy(*freeK11Space, svcCustomBackdoor_bin, svcCustomBackdoor_bin_size);
|
||||
*((u32 *)*freeK11Space + 1) = arm11SvcTable[0x2F]; // temporary location
|
||||
arm11SvcTable[0x2F] = 0xFFFF0000 + *freeK11Space - (u8 *)arm11ExceptionsPage;
|
||||
(*freeK11Space) += svcCustomBackdoor_bin_size;
|
||||
//Patch DebugActiveProcess
|
||||
for(off = (u32 *)(pos + (arm11SvcTable[0x60] - baseK11VA)); *off != 0xE3110001; off++);
|
||||
*off = 0xE3B01001; // tst r1, #1 -> movs r1, #1
|
||||
|
||||
for(off = (u32 *)(pos + (arm11SvcTable[0x7C] - baseK11VA)); off[0] != 0xE5D00001 || off[1] != 0xE3500000; off++);
|
||||
off[2] = 0xE1A00000; // in case 6: beq -> nop
|
||||
|
||||
//Patch kernelpanic
|
||||
off = (u32 *)memsearch(pos, patternKPanic, size, sizeof(patternKPanic));
|
||||
if(off == NULL)
|
||||
return 1;
|
||||
|
||||
off[-6] = 0xE12FFF7E;
|
||||
|
||||
//Redirect enableUserExceptionHandlersForCPUExc (= true)
|
||||
for(off = arm11ExceptionsPage; *off != 0x96007F9; off++);
|
||||
off[1] = 0x40000028;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 patchSignatureChecks(u8 *pos, u32 size)
|
||||
|
@ -41,10 +41,8 @@ extern CfgData configData;
|
||||
|
||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage);
|
||||
void installMMUHook(u8 *pos, u32 size, u8 **freeK11Space);
|
||||
void installK11MainHook(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage, u8 **freeK11Space);
|
||||
void installSvcConnectToPortInitHook(u32 *arm11SvcTable, u32 *arm11ExceptionsPage, u8 **freeK11Space);
|
||||
void installSvcCustomBackdoor(u32 *arm11SvcTable, u8 **freeK11Space, u32 *arm11ExceptionsPage);
|
||||
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space);
|
||||
u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage);
|
||||
u32 patchSignatureChecks(u8 *pos, u32 size);
|
||||
u32 patchOldSignatureChecks(u8 *pos, u32 size);
|
||||
u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
|
||||
|
@ -36,6 +36,9 @@
|
||||
#define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i)
|
||||
#define REG_TIMER_VAL(i) *(vu16 *)(0x10003000 + 4 * i)
|
||||
|
||||
#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
|
||||
#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
|
||||
|
||||
u32 waitInput(bool isMenu);
|
||||
void mcuPowerOff(void);
|
||||
void wait(u64 amount);
|
||||
|
@ -204,12 +204,15 @@ static Result loader_GetProgramInfo(exheader_header *exheader, u64 prog_handle)
|
||||
|
||||
if (R_SUCCEEDED(res))
|
||||
{
|
||||
s64 nbSection0Modules;
|
||||
svcGetSystemInfo(&nbSection0Modules, 26, 0);
|
||||
|
||||
// Force always having sdmc:/ and nand:/rw permission
|
||||
exheader->arm11systemlocalcaps.storageinfo.accessinfo[0] |= 0x480;
|
||||
exheader->accessdesc.arm11systemlocalcaps.storageinfo.accessinfo[0] |= 0x480;
|
||||
|
||||
// Tweak 3dsx placeholder title exheader
|
||||
if (exheader->arm11systemlocalcaps.programid == HBLDR_3DSX_TID)
|
||||
if (nbSection0Modules == 6 && exheader->arm11systemlocalcaps.programid == HBLDR_3DSX_TID)
|
||||
{
|
||||
Handle hbldr = 0;
|
||||
res = HBLDR_Init(&hbldr);
|
||||
|
@ -736,11 +736,17 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro
|
||||
}
|
||||
}
|
||||
|
||||
s64 nbSection0Modules;
|
||||
svcGetSystemInfo(&nbSection0Modules, 26, 0);
|
||||
|
||||
if(nbSection0Modules == 6)
|
||||
{
|
||||
// Makes ErrDisp to not start up
|
||||
static const u64 errDispTid = 0x0004003000008A02ULL;
|
||||
u32 *errDispTidLoc = (u32 *)memsearch(code, &errDispTid, size, sizeof(errDispTid));
|
||||
*(errDispTidLoc - 6) = 0xE3A00000; // mov r0, #0
|
||||
}
|
||||
}
|
||||
|
||||
else if(progId == 0x0004013000001702LL) //CFG
|
||||
{
|
||||
|
@ -17,7 +17,6 @@ dir_source := source
|
||||
dir_include := include
|
||||
dir_build := build
|
||||
dir_out := ../../$(dir_build)
|
||||
dir_kernel_extension := kernel_extension
|
||||
|
||||
LIBS := -lctru
|
||||
LIBDIRS := $(CTRULIB)
|
||||
@ -42,21 +41,14 @@ all: $(dir_out)/$(name).cxi
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(MAKE) -C $(dir_kernel_extension) clean
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
.PHONY: $(dir_kernel_extension)
|
||||
|
||||
$(dir_out)/$(name).cxi: $(dir_build)/$(name).elf
|
||||
@makerom -f ncch -rsf rosalina.rsf -nocodepadding -o $@ -elf $<
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
$(LINK.o) $(OUTPUT_OPTION) $^ $(LIBPATHS) $(LIBS)
|
||||
|
||||
$(dir_build)/kernel_extension.bin: $(dir_kernel_extension)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/xml_data.h: $(xml_files)
|
||||
@ echo "" > $(@)
|
||||
@$(foreach f, $(xml_files),\
|
||||
@ -66,7 +58,6 @@ $(dir_build)/xml_data.h: $(xml_files)
|
||||
)
|
||||
$(dir_build)/gdb/xfer.o: $(dir_build)/xml_data.h
|
||||
$(dir_build)/memory.o : CFLAGS += -O3
|
||||
$(dir_build)/kernel_extension.o: $(dir_build)/kernel_extension.bin
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
|
@ -1,14 +0,0 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
. = ALIGN(4);
|
||||
}
|
@ -146,7 +146,7 @@ void ERRF_DisplayError(ERRF_FatalErrInfo *info)
|
||||
switch(info->type)
|
||||
{
|
||||
case ERRF_ERRTYPE_CARD_REMOVED:
|
||||
desc = "The Game Card was removed.";
|
||||
desc = "The card was removed.";
|
||||
break;
|
||||
case ERRF_ERRTYPE_MEM_CORRUPT:
|
||||
desc = "The System Memory has been damaged.";
|
||||
|
@ -1,148 +0,0 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 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 and 7.c of GPLv3 apply 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.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#include "kernel_extension.h"
|
||||
#include "kernel_extension_setup.h"
|
||||
|
||||
#define MPCORE_REGS_BASE ((u32)PA_PTR(0x17E00000))
|
||||
#define MPCORE_GID_REGS_BASE (MPCORE_REGS_BASE + 0x1000)
|
||||
#define MPCORE_GID_SGI (*(vu32 *)(MPCORE_GID_REGS_BASE + 0xF00))
|
||||
|
||||
struct Parameters
|
||||
{
|
||||
void (*SGI0HandlerCallback)(struct Parameters *, u32 *);
|
||||
void *interruptManager;
|
||||
u32 *L2MMUTable; // bit31 mapping
|
||||
|
||||
void (*initFPU)(void);
|
||||
void (*mcuReboot)(void);
|
||||
void (*coreBarrier)(void);
|
||||
|
||||
u32 TTBCR;
|
||||
u32 L1MMUTableAddrs[4];
|
||||
|
||||
u32 kernelVersion;
|
||||
|
||||
struct CfwInfo
|
||||
{
|
||||
char magic[4];
|
||||
|
||||
u8 versionMajor;
|
||||
u8 versionMinor;
|
||||
u8 versionBuild;
|
||||
u8 flags;
|
||||
|
||||
u32 commitHash;
|
||||
|
||||
u32 config;
|
||||
} __attribute__((packed)) info;
|
||||
};
|
||||
|
||||
|
||||
static void K_SGI0HandlerCallback(volatile struct Parameters *p)
|
||||
{
|
||||
u32 L1MMUTableAddr;
|
||||
vu32 *L1MMUTable;
|
||||
u32 coreId;
|
||||
|
||||
__asm__ volatile("cpsid aif"); // disable interrupts
|
||||
|
||||
p->coreBarrier();
|
||||
|
||||
__asm__ volatile("mrc p15, 0, %0, c0, c0, 5" : "=r"(coreId));
|
||||
coreId &= 3;
|
||||
|
||||
__asm__ volatile("mrc p15, 0, %0, c2, c0, 1" : "=r"(L1MMUTableAddr));
|
||||
L1MMUTableAddr &= ~0x3FFF;
|
||||
p->L1MMUTableAddrs[coreId] = L1MMUTableAddr;
|
||||
L1MMUTable = (vu32 *)(L1MMUTableAddr | (1 << 31));
|
||||
|
||||
// Actually map the kernel ext
|
||||
u32 L2MMUTableAddr = (u32)(p->L2MMUTable) & ~(1 << 31);
|
||||
L1MMUTable[0x40000000 >> 20] = L2MMUTableAddr | 1;
|
||||
|
||||
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (0) : "memory");
|
||||
((void (*)(volatile struct Parameters *))0x40000000)(p);
|
||||
|
||||
p->coreBarrier();
|
||||
}
|
||||
|
||||
static u32 ALIGN(0x400) L2MMUTableFor0x40000000[256] = { 0 };
|
||||
u32 TTBCR;
|
||||
static void K_ConfigureSGI0(void)
|
||||
{
|
||||
// see /patches/k11MainHook.s
|
||||
u32 *off;
|
||||
u32 *initFPU, *mcuReboot, *coreBarrier;
|
||||
|
||||
// Search for stuff in the 0xFFFF0000 page
|
||||
for(initFPU = (u32 *)0xFFFF0000; initFPU < (u32 *)0xFFFF1000 && *initFPU != 0xE1A0D002; initFPU++);
|
||||
initFPU += 3;
|
||||
|
||||
for(mcuReboot = initFPU; mcuReboot < (u32 *)0xFFFF1000 && *mcuReboot != 0xE3A0A0C2; mcuReboot++);
|
||||
mcuReboot--;
|
||||
coreBarrier = (u32 *)decodeARMBranch(mcuReboot - 4);
|
||||
|
||||
for(off = mcuReboot; off < (u32 *)0xFFFF1000 && *off != 0x726C6468; off++); // "hdlr"
|
||||
|
||||
volatile struct Parameters *p = (struct Parameters *)PA_FROM_VA_PTR(off); // Caches? What are caches?
|
||||
p->SGI0HandlerCallback = (void (*)(struct Parameters *, u32 *))PA_FROM_VA_PTR(K_SGI0HandlerCallback);
|
||||
p->L2MMUTable = (u32 *)PA_FROM_VA_PTR(L2MMUTableFor0x40000000);
|
||||
p->initFPU = (void (*) (void))initFPU;
|
||||
p->mcuReboot = (void (*) (void))mcuReboot;
|
||||
p->coreBarrier = (void (*) (void))coreBarrier;
|
||||
|
||||
__asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(TTBCR));
|
||||
p->TTBCR = TTBCR;
|
||||
|
||||
p->kernelVersion = *(vu32 *)0x1FF80000;
|
||||
|
||||
// Now let's configure the L2 table
|
||||
|
||||
//4KB extended small pages: [SYS:RW USR:-- X TYP:NORMAL SHARED OUTER NOCACHE, INNER CACHED WB WA]
|
||||
for(u32 offset = 0; offset < kernel_extension_size; offset += 0x1000)
|
||||
L2MMUTableFor0x40000000[offset >> 12] = (u32)convertVAToPA(kernel_extension + offset) | 0x516;
|
||||
}
|
||||
|
||||
static void K_SendSGI0ToAllCores(void)
|
||||
{
|
||||
MPCORE_GID_SGI = 0xF0000; // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360f/CACGDJJC.html
|
||||
}
|
||||
|
||||
static inline void flushAllCaches(void)
|
||||
{
|
||||
svcUnmapProcessMemory(CUR_PROCESS_HANDLE, 0, 0); // this SVC flush both caches entirely (and properly) even when returing an error
|
||||
}
|
||||
|
||||
void installKernelExtension(void)
|
||||
{
|
||||
svc0x2F(K_ConfigureSGI0);
|
||||
flushAllCaches();
|
||||
svc0x2F(K_SendSGI0ToAllCores);
|
||||
flushAllCaches();
|
||||
|
||||
*(volatile bool *)0x1FF81108 = true;
|
||||
}
|
@ -33,7 +33,6 @@
|
||||
#include "hbloader.h"
|
||||
#include "utils.h"
|
||||
#include "MyThread.h"
|
||||
#include "kernel_extension_setup.h"
|
||||
#include "menus/process_patches.h"
|
||||
|
||||
// this is called before main
|
||||
@ -67,18 +66,15 @@ void __ctru_exit()
|
||||
__appExit();
|
||||
__sync_fini();
|
||||
__libc_fini_array();
|
||||
svcSleepThread(-1LL); // kernel-loaded sysmodules except PXI are not supposed to terminate anyways
|
||||
for(;;) svcSleepThread(0); // kernel-loaded sysmodules except PXI are not supposed to terminate anyways
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
|
||||
void initSystem()
|
||||
{
|
||||
__libc_init_array();
|
||||
|
||||
HBLDR_3DSX_TID = HBLDR_DEFAULT_3DSX_TID;
|
||||
installKernelExtension();
|
||||
|
||||
__libc_init_array();
|
||||
__sync_init();
|
||||
__appInit();
|
||||
}
|
||||
|
Reference in New Issue
Block a user