Move the kext outside Rosalina

- Stability (tm)
- Boots 1s faster on N3DS
- (∩ ͡° ͜ʖ ͡°)⊃━☆゚
This commit is contained in:
TuxSH 2017-06-13 02:00:41 +02:00
parent ae8ea7da16
commit e1d0602f25
78 changed files with 357 additions and 605 deletions

View File

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

View File

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

View File

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

View File

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

View 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
View 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__ = .;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.";

View File

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

View File

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