Added Rosalina, see details

- see release notes
- ( ͡° ͜ʖ ͡°)( ͡° ͜ʖ ͡°)( ͡° ͜ʖ ͡°)
- (∩ ͡° ͜ʖ ͡°)⊃━☆゚
- ( ͡ᵔ ͜ʖ ͡ᵔ) ♫┌( ͡° ͜ʖ ͡°)┘♪ ♫└( ͡° ͜ʖ ͡°)┐♪
This commit is contained in:
TuxSH
2017-06-05 02:02:04 +02:00
parent 4429cb2095
commit 21db0d45bd
226 changed files with 20505 additions and 1320 deletions

View File

@@ -0,0 +1,249 @@
@ 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.
.macro TEST_IF_MODE_AND_ARM_INST_OR_JUMP lbl, mode
cpsid aif
mrs sp, spsr
tst sp, #0x20
bne \lbl
and sp, #0x1f @ get previous processor mode
cmp sp, #\mode
bne \lbl
sub sp, lr, #4
mcr p15, 0, sp, c7, c8, 0 @ VA to PA translation with privileged read permission check
mrc p15, 0, sp, c7, c4, 0 @ read PA register
tst sp, #1 @ failure bit
bne \lbl
.endm
.macro GEN_USUAL_HANDLER name, index, pos
\name\()Handler:
ldr sp, =exceptionStackTop
ldr sp, [sp]
sub sp, #0x100
push {r0-r12, lr}
mrs r0, spsr
bl isExceptionFatal
cmp r0, #0
pop {r0-r12, lr}
bne _exc_is_fatal_\name
ldr sp, =originalHandlers
ldr sp, [sp, #\pos]
bx sp
_exc_is_fatal_\name:
push {r8, r9}
mov r8, #\index
b _commonHandler
.endm
.text
.arm
.balign 4
_die:
cpsid aif
_die_loop:
wfi
b _die_loop
_commonHandler:
cpsid aif
push {r0}
ldr r0, =_fatalExceptionOccured
ldr r0, [r0]
cmp r0, #0
bne _die_loop
pop {r0}
ldr r9, =_regs
stmia r9, {r0-r7}
mov r1, r8
pop {r8,r9}
ldr r0, =_fatalExceptionOccured
mov r4, #1
_try_lock:
ldrex r2, [r0]
strex r3, r4, [r0]
cmp r3, #0
bne _try_lock
push {r1, r12, lr} @ attempt to hang the other cores
adr r0, _die
mov r1, #0xf
mov r2, #1
mov r3, #0
bl executeFunctionOnCores
pop {r1, r12, lr}
mrs r2, spsr
mrs r3, cpsr
ldr r6, =_regs
add r6, #0x20
ands r4, r2, #0xf @ get the mode that triggered the exception
moveq r4, #0xf @ usr => sys
bic r5, r3, #0xf
orr r5, r4
msr cpsr_c, r5 @ change processor mode
stmia r6!, {r8-lr}
msr cpsr_c, r3 @ restore processor mode
str lr, [r6], #4
str r2, [r6], #4
mov r0, r6
mrc p15, 0, r4, c5, c0, 0 @ dfsr
mrc p15, 0, r5, c5, c0, 1 @ ifsr
mrc p15, 0, r6, c6, c0, 0 @ far
fmrx r7, fpexc
fmrx r8, fpinst
fmrx r9, fpinst2
bic r3, #(1<<31)
fmxr fpexc, r3 @ clear the VFP11 exception flag (if it's set)
stmia r0!, {r4-r9}
mov r0, #0
mcr p15, 0, r0, c7, c14, 0 @ Clean and Invalidate Entire Data Cache
mcr p15, 0, r0, c7, c10, 4 @ Drain Synchronization Barrier
ldr r0, =isN3DS
ldr r0, [r0]
cmp r0, #0
beq _no_L2C
ldr r0, =(0x17e10100 | 1 << 31)
ldr r0, [r0]
tst r0, #1 @ is the L2C enabled?
beq _no_L2C
ldr r0, =0xffff
ldr r2, =(0x17e10730 | 1 << 31)
str r0, [r2, #0x4c] @ invalidate by way
_L2C_sync:
ldr r0, [r2] @ L2C cache sync register
tst r0, #1
bne _L2C_sync
_no_L2C:
cps #0x1F
ldr sp, =exceptionStackTop
ldr sp, [sp]
sub sp, #0x100
mov r0, #0
mcr p15, 0, r0, c7, c10, 5 @ Drain Memory Barrier
ldr r0, =_regs
mrc p15, 0, r2, c0, c0, 5 @ CPU ID register
bl fatalExceptionHandlersMain
ldr r12, =mcuReboot
ldr r12, [r12]
bx r12
.global FIQHandler
.type FIQHandler, %function
GEN_USUAL_HANDLER FIQ, 0, 28
.global undefinedInstructionHandler
.type undefinedInstructionHandler, %function
undefinedInstructionHandler:
TEST_IF_MODE_AND_ARM_INST_OR_JUMP _undefinedInstructionNormalHandler, 0x10
ldr sp, [lr, #-4] @ test if it's an VFP instruction that was aborted
lsl sp, #4
sub sp, #0xc0000000
cmp sp, #0x30000000
bcs _undefinedInstructionNormalHandler
fmrx sp, fpexc
tst sp, #0x40000000
bne _undefinedInstructionNormalHandler
@ FPU init
sub lr, #4
srsfd sp!, #0x13
cps #0x13
stmfd sp, {r0-r3, r11-lr}^
sub sp, #0x20
ldr r12, =initFPU
ldr r12, [r12]
blx r12
ldmfd sp, {r0-r3, r11-lr}^
add sp, #0x20
rfefd sp! @ retry aborted instruction
GEN_USUAL_HANDLER _undefinedInstructionNormal, 1, 4
.global prefetchAbortHandler
.type prefetchAbortHandler, %function
prefetchAbortHandler:
TEST_IF_MODE_AND_ARM_INST_OR_JUMP _prefetchAbortNormalHandler, 0x13
ldr sp, =(Break + 3*4 + 4)
cmp lr, sp
bne _prefetchAbortNormalHandler
sub sp, r0, #0x110
pop {r0-r7, r12, lr}
pop {r8-r11}
ldr lr, [sp, #8]!
ldr sp, [sp, #4]
msr spsr, sp
addne lr, #2 @ adjust address for later
GEN_USUAL_HANDLER _prefetchAbortNormal, 2, 12
.global dataAbortHandler
.type dataAbortHandler, %function
dataAbortHandler:
ldr sp, =exceptionStackTop
ldr sp, [sp]
push {r0-r12, lr}
mrs r0, spsr
sub r1, lr, #8
bl isDataAbortExceptionRangeControlled
cmp r0, #0
pop {r0-r12, lr}
beq _dataAbortNormalHandler
msr spsr_f, #(1 << 30)
mov r12, #0
subs pc, lr, #4
GEN_USUAL_HANDLER _dataAbortNormal, 3, 16
.bss
.balign 4
_regs: .skip (4 * 23)
_fatalExceptionOccured: .word 0

View File

@@ -0,0 +1,125 @@
/*
* 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 "fatalExceptionHandlers.h"
#include "utils.h"
#include "kernel.h"
#include "memory.h"
#include "globals.h"
#define REG_DUMP_SIZE 4 * 23
#define CODE_DUMP_SIZE 48
bool isExceptionFatal(u32 spsr)
{
if((spsr & 0x1f) != 0x10) return true;
KThread *thread = currentCoreContext->objectContext.currentThread;
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
if(thread != NULL && thread->threadLocalStorage != NULL && *((vu32 *)thread->threadLocalStorage + 0x10) != 0)
return false;
if(currentProcess != NULL)
{
if(debugOfProcess(currentProcess) != NULL)
return false;
thread = KPROCESS_GET_RVALUE(currentProcess, mainThread);
if(thread != NULL && thread->threadLocalStorage != NULL && *((vu32 *)thread->threadLocalStorage + 0x10) != 0)
return false;
}
return true;
}
extern u32 safecpy_sz;
bool isDataAbortExceptionRangeControlled(u32 spsr, u32 addr)
{
return ((spsr & 0x1F) != 0x10) && (
((u32)kernelUsrCopyFuncsStart <= addr && addr < (u32)kernelUsrCopyFuncsEnd) ||
((u32)safecpy <= addr && addr < (u32)safecpy + safecpy_sz)
);
}
void fatalExceptionHandlersMain(u32 *registerDump, u32 type, u32 cpuId)
{
ExceptionDumpHeader dumpHeader;
u8 codeDump[CODE_DUMP_SIZE];
u8 *finalBuffer = (u8 *)PA_PTR(0x25000000);
u8 *final = finalBuffer;
dumpHeader.magic[0] = 0xDEADC0DE;
dumpHeader.magic[1] = 0xDEADCAFE;
dumpHeader.versionMajor = 1;
dumpHeader.versionMinor = 2;
dumpHeader.processor = 11;
dumpHeader.core = cpuId & 0xF;
dumpHeader.type = type;
dumpHeader.registerDumpSize = REG_DUMP_SIZE;
dumpHeader.codeDumpSize = CODE_DUMP_SIZE;
u32 cpsr = registerDump[16];
u32 pc = registerDump[15] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
registerDump[15] = pc;
//Dump code
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem
dumpHeader.codeDumpSize = ((u32)instr & (((cpsr & 0x20) != 0) ? 1 : 3)) != 0 ? 0 : safecpy(codeDump, instr, dumpHeader.codeDumpSize);
//Copy register dump and code dump
final = (u8 *)(finalBuffer + sizeof(ExceptionDumpHeader));
memcpy(final, registerDump, dumpHeader.registerDumpSize);
final += dumpHeader.registerDumpSize;
memcpy(final, codeDump, dumpHeader.codeDumpSize);
final += dumpHeader.codeDumpSize;
//Dump stack in place
dumpHeader.stackDumpSize = safecpy(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF));
final += dumpHeader.stackDumpSize;
if(currentCoreContext->objectContext.currentProcess)
{
vu64 *additionalData = (vu64 *)final;
KCodeSet *currentCodeSet = codeSetOfProcess(currentCoreContext->objectContext.currentProcess);
if(currentCodeSet != NULL)
{
dumpHeader.additionalDataSize = 16;
memcpy((void *)additionalData, currentCodeSet->processName, 8);
additionalData[1] = currentCodeSet->titleId;
}
else dumpHeader.additionalDataSize = 0;
}
else dumpHeader.additionalDataSize = 0;
dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize;
//Copy header (actually optimized by the compiler)
*(ExceptionDumpHeader *)finalBuffer = dumpHeader;
}

View File

@@ -0,0 +1,104 @@
/*
* 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 "globals.h"
KRecursiveLock *criticalSectionLock;
KObjectList *threadList;
KObjectMutex *synchronizationMutex;
void (*KRecursiveLock__Lock)(KRecursiveLock *this);
void (*KRecursiveLock__Unlock)(KRecursiveLock *this);
void (*KAutoObject__AddReference)(KAutoObject *this);
KProcess * (*KProcessHandleTable__ToKProcess)(KProcessHandleTable *this, Handle processHandle);
KThread * (*KProcessHandleTable__ToKThread)(KProcessHandleTable *this, Handle threadHandle);
KAutoObject * (*KProcessHandleTable__ToKAutoObject)(KProcessHandleTable *this, Handle handle);
void (*KSynchronizationObject__Signal)(KSynchronizationObject *this, bool isPulse);
Result (*WaitSynchronization1)(void *this_unused, KThread *thread, KSynchronizationObject *syncObject, s64 timeout);
Result (*KProcessHandleTable__CreateHandle)(KProcessHandleTable *this, Handle *out, KAutoObject *obj, u8 token);
Result (*KProcessHwInfo__MapProcessMemory)(KProcessHwInfo *this, KProcessHwInfo *other, void *dst, void *src, u32 nbPages);
Result (*KProcessHwInfo__UnmapProcessMemory)(KProcessHwInfo *this, void *addr, u32 nbPages);
Result (*KEvent__Clear)(KEvent *this);
void (*KObjectMutex__WaitAndAcquire)(KObjectMutex *this);
void (*KObjectMutex__ErrorOccured)(void);
void (*KScheduler__AdjustThread)(KScheduler *this, KThread *thread, u32 oldSchedulingMask);
void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
void (*SleepThread)(s64 ns);
Result (*CloseHandle)(Handle handle);
Result (*GetSystemInfo)(s64 *out, s32 type, s32 param);
Result (*GetProcessInfo)(s64 *out, Handle processHandle, u32 type);
Result (*GetThreadInfo)(s64 *out, Handle threadHandle, u32 type);
Result (*ConnectToPort)(Handle *out, const char *name);
Result (*SendSyncRequest)(Handle handle);
Result (*OpenProcess)(Handle *out, u32 processId);
Result (*GetProcessId)(u32 *out, Handle process);
Result (*DebugActiveProcess)(Handle *out, u32 processId);
Result (*KernelSetState)(u32 type, u32 varg1, u32 varg2, u32 varg3);
void (*flushDataCacheRange)(void *addr, u32 len);
void (*invalidateInstructionCacheRange)(void *addr, u32 len);
bool (*usrToKernelMemcpy8)(void *dst, const void *src, u32 len);
bool (*usrToKernelMemcpy32)(u32 *dst, const u32 *src, u32 len);
s32 (*usrToKernelStrncpy)(char *dst, const char *src, u32 len);
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);
Result (*SignalDebugEvent)(DebugEventType type, u32 info, ...);
bool isN3DS;
u32 *exceptionStackTop;
u32 TTBCR;
u32 L1MMUTableAddrs[4];
u32 kernelVersion;
void *kernelUsrCopyFuncsStart, *kernelUsrCopyFuncsEnd;
bool *isDevUnit;
InterruptManager *interruptManager;
KBaseInterruptEvent *customInterruptEvent;
void (*initFPU)(void);
void (*mcuReboot)(void);
void (*coreBarrier)(void);
CfwInfo cfwInfo;
u32 rosalinaState;
bool hasStartedRosalinaNetworkFuncsOnce;

View File

@@ -0,0 +1,321 @@
/*
* 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 "ipc.h"
#include "memory.h"
static SessionInfo sessionInfos[MAX_SESSION] = { {NULL} };
static u32 nbActiveSessions = 0;
static KRecursiveLock sessionInfosLock = { NULL };
KRecursiveLock processLangemuLock;
LangemuAttributes processLangemuAttributes[0x40];
static void *customSessionVtable[0x10] = { NULL }; // should be enough
static u32 SessionInfo_FindClosestSlot(KSession *session)
{
if(nbActiveSessions == 0 || session <= sessionInfos[0].session)
return 0;
else if(session > sessionInfos[nbActiveSessions - 1].session)
return nbActiveSessions;
u32 a = 0, b = nbActiveSessions - 1, m;
do
{
m = (a + b) / 2;
if(sessionInfos[m].session < session)
a = m;
else if(sessionInfos[m].session > session)
b = m;
else
return m;
}
while(b - a > 1);
return b;
}
SessionInfo *SessionInfo_Lookup(KSession *session)
{
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&sessionInfosLock);
SessionInfo *ret;
u32 id = SessionInfo_FindClosestSlot(session);
if(id == nbActiveSessions)
ret = NULL;
else
ret = (void **)(sessionInfos[id].session->autoObject.vtable) == customSessionVtable ? &sessionInfos[id] : NULL;
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
return ret;
}
SessionInfo *SessionInfo_FindFirst(const char *name)
{
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&sessionInfosLock);
SessionInfo *ret;
u32 id;
for(id = 0; id < nbActiveSessions && strncmp(sessionInfos[id].name, name, 12) != 0; id++);
if(id == nbActiveSessions)
ret = NULL;
else
ret = (void **)(sessionInfos[id].session->autoObject.vtable) == customSessionVtable ? &sessionInfos[id] : NULL;
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
return ret;
}
void SessionInfo_Add(KSession *session, const char *name)
{
KAutoObject__AddReference(&session->autoObject);
SessionInfo_ChangeVtable(session);
session->autoObject.vtable->DecrementReferenceCount(&session->autoObject);
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&sessionInfosLock);
if(nbActiveSessions == MAX_SESSION)
{
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
return;
}
u32 id = SessionInfo_FindClosestSlot(session);
if(id != nbActiveSessions && sessionInfos[id].session == session)
{
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
return;
}
for(u32 i = nbActiveSessions; i > id && i != 0; i--)
sessionInfos[i] = sessionInfos[i - 1];
nbActiveSessions++;
sessionInfos[id].session = session;
strncpy(sessionInfos[id].name, name, 12);
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
}
void SessionInfo_Remove(KSession *session)
{
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&sessionInfosLock);
if(nbActiveSessions == MAX_SESSION)
{
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
return;
}
u32 id = SessionInfo_FindClosestSlot(session);
if(id == nbActiveSessions)
{
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
return;
}
for(u32 i = id; i < nbActiveSessions - 1; i++)
sessionInfos[i] = sessionInfos[i + 1];
memset(&sessionInfos[--nbActiveSessions], 0, sizeof(SessionInfo));
KRecursiveLock__Unlock(&sessionInfosLock);
KRecursiveLock__Unlock(criticalSectionLock);
}
static void (*KSession__dtor_orig)(KAutoObject *this);
static void KSession__dtor_hook(KAutoObject *this)
{
KSession__dtor_orig(this);
SessionInfo_Remove((KSession *)this);
}
void SessionInfo_ChangeVtable(KSession *session)
{
if(customSessionVtable[2] == NULL)
{
memcpy(customSessionVtable, session->autoObject.vtable, 0x40);
KSession__dtor_orig = session->autoObject.vtable->dtor;
customSessionVtable[2] = (void *)KSession__dtor_hook;
}
session->autoObject.vtable = (Vtable__KAutoObject *)customSessionVtable;
}
bool doLangEmu(Result *res, Handle handle, u32 *cmdbuf)
{
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&processLangemuLock);
u64 titleId = codeSetOfProcess(currentCoreContext->objectContext.currentProcess)->titleId;
LangemuAttributes *attribs = NULL;
bool skip = true;
*res = 0;
for(u32 i = 0; i < 0x40; i++)
{
if(processLangemuAttributes[i].titleId == titleId)
attribs = &processLangemuAttributes[i];
}
if(attribs == NULL)
{
KRecursiveLock__Unlock(&processLangemuLock);
KRecursiveLock__Unlock(criticalSectionLock);
return false;
}
if((cmdbuf[0] == 0x20000 || cmdbuf[0] == 0x4060000 || cmdbuf[0] == 0x8160000) && (attribs->mask & 1)) // SecureInfoGetRegion
{
cmdbuf[0] = (cmdbuf[0] & 0xFFFF0000) | 0x80;
cmdbuf[1] = 0;
cmdbuf[2] = attribs->region;
}
else if(cmdbuf[1] == 1 && cmdbuf[2] == 0xA0002 && cmdbuf[3] == 0x1C && (attribs->mask & 2))
{
cmdbuf[0] = (cmdbuf[0] & 0xFFFF0000) | 0x40;
cmdbuf[1] = 0;
*(u8 *)cmdbuf[4] = attribs->language;
}
else if(cmdbuf[1] == 4 && cmdbuf[2] == 0xB0000 && cmdbuf[3] == 0x4C && (attribs->mask & 0xC))
{
u8 *ptr = (u8 *)cmdbuf[4];
*res = SendSyncRequest(handle);
flushEntireDataCache(); // looks like it's needed. WTF?!
if(*res == 0)
{
if(attribs->mask & 4)
ptr[3] = attribs->country;
if(attribs->mask & 8)
ptr[2] = attribs->state;
}
}
else
skip = false;
KRecursiveLock__Unlock(&processLangemuLock);
KRecursiveLock__Unlock(criticalSectionLock);
return skip;
}
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf)
{
Result res = 0;
u32 pid;
bool terminateRosalina = cmdbuf[1] == 0x100 && cmdbuf[2] == 0; // cmdbuf[2] to check for well-formed requests
u32 savedCmdbuf[4];
memcpy(savedCmdbuf, cmdbuf, 16);
if(!terminateRosalina || GetProcessId(&pid, cmdbuf[3]) != 0)
terminateRosalina = false;
else
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KProcess *process = KProcessHandleTable__ToKProcess(handleTable, cmdbuf[3]);
if((strcmp(codeSetOfProcess(process)->processName, "socket") == 0 && (rosalinaState & 2)) ||
strcmp(codeSetOfProcess(process)->processName, "pxi") == 0)
terminateRosalina = true;
else
terminateRosalina = false;
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
}
if(terminateRosalina)
{
Handle rosalinaProcessHandle;
res = OpenProcess(&rosalinaProcessHandle, 5);
if(res == 0)
{
cmdbuf[0] = cmdbuf[0];
cmdbuf[1] = 0x100;
cmdbuf[2] = 0;
cmdbuf[3] = rosalinaProcessHandle;
res = SendSyncRequest(handle);
CloseHandle(rosalinaProcessHandle);
memcpy(cmdbuf, savedCmdbuf, 16);
}
}
return SendSyncRequest(handle);
}
bool doErrfThrowHook(u32 *cmdbuf)
{
// If fatalErrorInfo->type is "card removed" or "logged", returning from ERRF:Throw is a no-op
// for the SDK function
// r6 (arm) or r4 (thumb) is copied into cmdbuf[1..31]
u32 *r0_to_r7_r12_usr = (u32 *)((u8 *)currentCoreContext->objectContext.currentThread->endOfThreadContext - 0x110);
u32 spsr = *(u32 *)((u8 *)currentCoreContext->objectContext.currentThread->endOfThreadContext - 0xCC);
u8 *srcerrbuf = (u8 *)r0_to_r7_r12_usr[(spsr & 0x20) ? 4 : 6];
const char *pname = codeSetOfProcess(currentCoreContext->objectContext.currentProcess)->processName;
static const struct
{
const char *name;
Result errCode;
} errorCodesToIgnore[] =
{
/*
If you're getting this error, you have broken your head-tracking hardware,
and should uncomment the following line:
*/
//{ "qtm", (Result)0xF96183FE },
{ "", 0 }, // impossible case to ensure the array has at least 1 element
};
for(u32 i = 0; i < sizeof(errorCodesToIgnore) / sizeof(errorCodesToIgnore[0]); i++)
{
if(strcmp(pname, errorCodesToIgnore[i].name) == 0 && (Result)cmdbuf[2] == errorCodesToIgnore[i].errCode)
{
srcerrbuf[0] = 5;
cmdbuf[0] = 0x10040;
cmdbuf[1] = 0;
return true;
}
}
return false;
}

View File

@@ -0,0 +1,310 @@
/*
* 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 "utils.h"
#include "globals.h"
#include "synchronization.h"
#include "fatalExceptionHandlers.h"
#include "svc.h"
#include "svc/ConnectToPort.h"
#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 };
static void setupSGI0Handler(void)
{
for(u32 i = 0; i < getNumberOfCores(); i++)
interruptManager->N3DS.privateInterrupts[i][0].interruptEvent = customInterruptEvent;
}
static inline void **getHandlerDestination(enum VECTORS vector)
{
u32 *branch_dst = (u32 *)decodeARMBranch((u32 *)exceptionsPage + (u32)vector);
return (void **)(branch_dst + 2);
}
static inline void swapHandlerInVeneer(enum VECTORS vector, void *handler)
{
void **dst = getHandlerDestination(vector);
originalHandlers[(u32)vector] = *dst;
if(handler != NULL)
*(void**)PA_FROM_VA_PTR(dst) = handler;
}
static u32 *trampo_;
static bool **enableUserExceptionHandlersForCPUExcLoc;
static bool enableUserExceptionHandlersForCPUExc = true;
static void setupSvcHandler(void)
{
swapHandlerInVeneer(SVC, svcHandler);
void **arm11SvcTable = (void**)originalHandlers[(u32)SVC];
while(*arm11SvcTable != NULL) arm11SvcTable++; //Look for SVC0 (NULL)
memcpy(officialSVCs, arm11SvcTable, 4 * 0x7E);
u32 *off;
for(off = (u32 *)officialSVCs[0x2D]; *off != 0x65736162; off++);
*(void **)PA_FROM_VA_PTR(arm11SvcTable + 0x2D) = officialSVCs[0x2D] = (void *)off[1];
trampo_ = (u32 *)PA_FROM_VA_PTR(off + 3);
CustomBackdoor = (Result (*)(void *, ...))((u32 *)officialSVCs[0x2F] + 2);
*(void **)PA_FROM_VA_PTR(arm11SvcTable + 0x2F) = officialSVCs[0x2F] = (void *)*((u32 *)officialSVCs[0x2F] + 1);
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();
}
static void findUsefulSymbols(void)
{
u32 *off;
KProcessHandleTable__ToKProcess = (KProcess * (*)(KProcessHandleTable *, Handle))decodeARMBranch(5 + (u32 *)officialSVCs[0x76]);
for(off = (u32 *)KProcessHandleTable__ToKProcess; *off != 0xE28DD014; off++);
KAutoObject__AddReference = (void (*)(KAutoObject *))decodeARMBranch(off - 1);
for(; *off != 0xE8BD80F0; off++);
KProcessHandleTable__ToKAutoObject = (KAutoObject * (*)(KProcessHandleTable *, Handle))decodeARMBranch(off + 2);
for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[9]); /* KThread::Terminate */ *off != 0xE5D42034; off++);
off -= 2;
criticalSectionLock = (KRecursiveLock *)off[2 + (off[0] & 0xFF) / 4];
KRecursiveLock__Lock = (void (*)(KRecursiveLock *))decodeARMBranch(off + 1);
off += 4;
for(; (*off >> 16) != 0xE59F; off++);
KRecursiveLock__Unlock = (void (*)(KRecursiveLock *))decodeARMBranch(off + 1);
for(; *off != 0xE5C4007D; off++);
KSynchronizationObject__Signal = (void (*)(KSynchronizationObject *, bool))decodeARMBranch(off + 3);
for(off = (u32 *)officialSVCs[0x19]; *off != 0xE1A04005; off++);
KEvent__Clear = (Result (*)(KEvent *))decodeARMBranch(off + 1);
for(off = (u32 *)KEvent__Clear; *off != 0xE8BD8070; off++)
synchronizationMutex = *(KObjectMutex **)(off + 1);
for(off = (u32 *)officialSVCs[0x24]; *off != 0xE59F004C; off++);
WaitSynchronization1 = (Result (*)(void *, KThread *, KSynchronizationObject *, s64))decodeARMBranch(off + 6);
for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[0x33]) /* OpenProcess */ ; *off != 0xE20030FF; off++);
KProcessHandleTable__CreateHandle = (Result (*)(KProcessHandleTable *, Handle *, KAutoObject *, u8))decodeARMBranch(off + 2);
for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[0x34]) /* OpenThread */; *off != 0xD9001BF7; off++);
threadList = *(KObjectList **)(off + 1);
KProcessHandleTable__ToKThread = (KThread * (*)(KProcessHandleTable *, Handle))decodeARMBranch((u32 *)decodeARMBranch((u32 *)officialSVCs[0x37] + 3) /* GetThreadId */ + 5);
for(off = (u32 *)officialSVCs[0x54]; *off != 0xE8BD8008; off++);
flushDataCacheRange = (void (*)(void *, u32))(*(u32 **)(off[1]) + 3);
for(off = (u32 *)officialSVCs[0x71]; *off != 0xE2101102; off++);
KProcessHwInfo__MapProcessMemory = (Result (*)(KProcessHwInfo *, KProcessHwInfo *, void *, void *, u32))decodeARMBranch(off - 1);
for(off = (u32 *)officialSVCs[0x72]; *off != 0xE2041102; off++);
KProcessHwInfo__UnmapProcessMemory = (Result (*)(KProcessHwInfo *, void *, u32))decodeARMBranch(off - 1);
for(off = (u32 *)officialSVCs[0x7C]; *off != 0x03530000; off++);
KObjectMutex__WaitAndAcquire = (void (*)(KObjectMutex *))decodeARMBranch(++off);
for(; *off != 0xE320F000; off++);
KObjectMutex__ErrorOccured = (void (*)(void))decodeARMBranch(off + 1);
for(off = (u32 *)originalHandlers[(u32) DATA_ABORT]; *off != (u32)exceptionStackTop; off++);
kernelUsrCopyFuncsStart = (void *)off[1];
kernelUsrCopyFuncsEnd = (void *)off[2];
u32 n_cmp_0;
for(off = (u32 *)kernelUsrCopyFuncsStart, n_cmp_0 = 1; n_cmp_0 <= 6; off++)
{
if(*off == 0xE3520000)
{
// We're missing some funcs
switch(n_cmp_0)
{
case 1:
usrToKernelMemcpy8 = (bool (*)(void *, const void *, u32))off;
break;
case 2:
usrToKernelMemcpy32 = (bool (*)(u32 *, const u32 *, u32))off;
break;
case 3:
usrToKernelStrncpy = (s32 (*)(char *, const char *, u32))off;
break;
case 4:
kernelToUsrMemcpy8 = (bool (*)(void *, const void *, u32))off;
break;
case 5:
kernelToUsrMemcpy32 = (bool (*)(u32 *, const u32 *, u32))off;
break;
case 6:
kernelToUsrStrncpy = (s32 (*)(char *, const char *, u32))off;
break;
default: break;
}
n_cmp_0++;
}
}
// The official prototype of ControlMemory doesn't have that extra param'
ControlMemory = (Result (*)(u32 *, u32, u32, u32, MemOp, MemPerm, bool))
decodeARMBranch((u32 *)officialSVCs[0x01] + 5);
SleepThread = (void (*)(s64))officialSVCs[0x0A];
CloseHandle = (Result (*)(Handle))officialSVCs[0x23];
GetSystemInfo = (Result (*)(s64 *, s32, s32))decodeARMBranch((u32 *)officialSVCs[0x2A] + 3);
GetProcessInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2B] + 3);
GetThreadInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2C] + 3);
ConnectToPort = (Result (*)(Handle *, const char*))decodeARMBranch((u32 *)officialSVCs[0x2D] + 3);
SendSyncRequest = (Result (*)(Handle))officialSVCs[0x32];
OpenProcess = (Result (*)(Handle *, u32))decodeARMBranch((u32 *)officialSVCs[0x33] + 3);
GetProcessId = (Result (*)(u32 *, Handle))decodeARMBranch((u32 *)officialSVCs[0x35] + 3);
DebugActiveProcess = (Result (*)(Handle *, u32))decodeARMBranch((u32 *)officialSVCs[0x60] + 3);
KernelSetState = (Result (*)(u32, u32, u32, u32))((u32 *)officialSVCs[0x7C] + 1);
for(off = (u32 *)svcFallbackHandler; *off != 0xE8BD4010; off++);
kernelpanic = (void (*)(void))off;
for(off = (u32 *)0xFFFF0000; off[0] != 0xE3A01002 || off[1] != 0xE3A00004; off++);
SignalDebugEvent = (Result (*)(DebugEventType type, u32 info, ...))decodeARMBranch(off + 2);
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 textSize = rodataStart - textStart;
for(off = (u32 *)textStart; off < (u32 *)(textStart + textSize) - 3; off++)
{
if(off[0] == 0xE5D13034 && off[1] == 0xE1530002)
KScheduler__AdjustThread = (void (*)(KScheduler *, KThread *, u32))off;
else if(off[0] == (u32)interruptManager && off[1] == (u32)&currentCoreContext->objectContext)
KScheduler__AttemptSwitchingThreadContext = (void (*)(KScheduler *))(off - 2);
else if(off[0] == 0xE3510B1A && off[1] == 0xE3A06000)
{
u32 *off2;
for(off2 = off; *off2 != 0xE92D40F8; off2--);
invalidateInstructionCacheRange = (void (*)(void *, u32))off2;
}
}
}
struct Parameters
{
void (*SGI0HandlerCallback)(struct Parameters *, u32 *);
InterruptManager *interruptManager;
u32 *L2MMUTable; // bit31 mapping
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.
*(bool **)PA_FROM_VA_PTR(enableUserExceptionHandlersForCPUExcLoc) = &enableUserExceptionHandlersForCPUExc;
u32 *off;
for(off = (u32 *)officialSVCs[0x7C]; off[0] != 0xE5D00001 || off[1] != 0xE3500000; off++);
*(u32 *)PA_FROM_VA_PTR(off + 2) = 0xE1A00000; // in case 6: beq -> nop
for(off = (u32 *)DebugActiveProcess; *off != 0xE3110001; off++);
*(u32 *)PA_FROM_VA_PTR(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 *)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 *)ControlMemory)); // ldr r0, [sp, #(frameSize + 8)]
}
void main(volatile struct Parameters *p)
{
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();
findUsefulSymbols();
enableDebugFeatures();
doOtherPatches();
rosalinaState = 0;
hasStartedRosalinaNetworkFuncsOnce = false;
*trampo_ = (u32)ConnectToPortHookWrapper;
}

View File

@@ -0,0 +1,176 @@
/*
* 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 "memory.h"
#include "utils.h"
void *memcpy(void *dest, const void *src, u32 size)
{
u8 *destc = (u8 *)dest;
const u8 *srcc = (const u8 *)src;
for(u32 i = 0; i < size; i++)
destc[i] = srcc[i];
return dest;
}
int memcmp(const void *buf1, const void *buf2, u32 size)
{
const u8 *buf1c = (const u8 *)buf1;
const u8 *buf2c = (const u8 *)buf2;
for(u32 i = 0; i < size; i++)
{
int cmp = buf1c[i] - buf2c[i];
if(cmp)
return cmp;
}
return 0;
}
void *memset(void *dest, u32 value, u32 size)
{
u8 *destc = (u8 *)dest;
for(u32 i = 0; i < size; i++) destc[i] = (u8)value;
return dest;
}
void *memset32(void *dest, u32 value, u32 size)
{
u32 *dest32 = (u32 *)dest;
for(u32 i = 0; i < size/4; i++) dest32[i] = value;
return dest;
}
//Boyer-Moore Horspool algorithm, adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
{
const u8 *patternc = (const u8 *)pattern;
u32 table[256];
//Preprocessing
for(u32 i = 0; i < 256; i++)
table[i] = patternSize;
for(u32 i = 0; i < patternSize - 1; i++)
table[patternc[i]] = patternSize - i - 1;
//Searching
u32 j = 0;
while(j <= size - patternSize)
{
u8 c = startPos[j + patternSize - 1];
if(patternc[patternSize - 1] == c && memcmp(pattern, startPos + j, patternSize - 1) == 0)
return startPos + j;
j += table[c];
}
return NULL;
}
char *strcpy(char *dest, const char *src)
{
u32 i;
for(i = 0; src[i] != 0; i++)
dest[i] = src[i];
dest[i] = 0;
return dest;
}
char *strncpy(char *dest, const char *src, u32 size)
{
u32 i;
for(i = 0; i < size && src[i] != 0; i++)
dest[i] = src[i];
for(; i < size; i++)
dest[i] = 0;
return dest;
}
s32 strnlen(const char *string, s32 maxlen)
{
s32 size;
for(size = 0; *string && size < maxlen; string++, size++);
return size;
}
s32 strlen(const char *string)
{
char *stringEnd = (char *)string;
while(*stringEnd) stringEnd++;
return stringEnd - string;
}
s32 strcmp(const char *str1, const char *str2)
{
while(*str1 && (*str1 == *str2))
{
str1++;
str2++;
}
return *str1 - *str2;
}
s32 strncmp(const char *str1, const char *str2, u32 size)
{
while(size && *str1 && (*str1 == *str2))
{
str1++;
str2++;
size--;
}
if (!size)
return 0;
else
return *str1 - *str2;
}
void hexItoa(u64 number, char *out, u32 digits, bool uppercase)
{
const char hexDigits[] = "0123456789ABCDEF";
const char hexDigitsLowercase[] = "0123456789abcdef";
u32 i = 0;
while(number > 0)
{
out[digits - 1 - i++] = uppercase ? hexDigits[number & 0xF] : hexDigitsLowercase[number & 0xF];
number >>= 4;
}
while(i < digits) out[digits - 1 - i++] = '0';
}

View File

@@ -0,0 +1,55 @@
@ 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.
.section .text.start
.balign 4
.global _start
_start:
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:
pop {r4, pc}
.bss
.balign 4
_setupFinished: .word 0

View File

@@ -0,0 +1,155 @@
/*
* 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 "svc.h"
#include "svc/ControlMemory.h"
#include "svc/GetProcessInfo.h"
#include "svc/GetThreadInfo.h"
#include "svc/GetSystemInfo.h"
#include "svc/GetCFWInfo.h"
#include "svc/ConnectToPort.h"
#include "svc/SendSyncRequest.h"
#include "svc/Break.h"
#include "svc/SetGpuProt.h"
#include "svc/SetWifiEnabled.h"
#include "svc/Backdoor.h"
#include "svc/KernelSetState.h"
#include "svc/MapProcessMemoryEx.h"
#include "svc/UnmapProcessMemoryEx.h"
#include "svc/ControlService.h"
#include "svc/CopyHandle.h"
#include "svc/TranslateHandle.h"
void *officialSVCs[0x7E] = {NULL};
static inline void yieldDuringRosalinaMenu(void)
{
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
u64 titleId = codeSetOfProcess(currentProcess)->titleId;
u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)titleId;
while((rosalinaState & 1) && idOfProcess(currentProcess) >= 6 &&
(highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))))
SleepThread(25 * 1000 * 1000LL);
}
void signalSvcEntry(u8 *pageEnd)
{
u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5);
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
yieldDuringRosalinaMenu();
if(svcId == 0xFE)
svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x3FFFFFFF. We don't support catching svcIds >= 0x100 atm either
// Since DBGEVENT_SYSCALL_ENTRY is non blocking, we'll cheat using EXCEVENT_UNDEFINED_SYSCALL (debug->svcId is fortunately an u16!)
if(debugOfProcess(currentProcess) != NULL && shouldSignalSyscallDebugEvent(currentProcess, svcId))
SignalDebugEvent(DBGEVENT_OUTPUT_STRING, 0xFFFFFFFE, svcId);
}
void signalSvcReturn(u8 *pageEnd)
{
u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5);
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
yieldDuringRosalinaMenu();
if(svcId == 0xFE)
svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x1FFFFFFF. We don't support catching svcIds >= 0x100 atm either
// Since DBGEVENT_SYSCALL_RETURN is non blocking, we'll cheat using EXCEVENT_UNDEFINED_SYSCALL (debug->svcId is fortunately an u16!)
if(debugOfProcess(currentProcess) != NULL && shouldSignalSyscallDebugEvent(currentProcess, svcId))
SignalDebugEvent(DBGEVENT_OUTPUT_STRING, 0xFFFFFFFF, svcId);
}
void *svcHook(u8 *pageEnd)
{
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
u32 svcId = *(u8 *)(pageEnd - 0xB5);
if(svcId == 0xFE)
svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x3FFFFFFF. We don't support catching svcIds >= 0x100 atm either
switch(svcId)
{
case 0x01:
return ControlMemoryHookWrapper;
case 0x2A:
return GetSystemInfoHookWrapper;
case 0x2B:
return GetProcessInfoHookWrapper;
case 0x2C:
return GetThreadInfoHookWrapper;
case 0x2D:
return ConnectToPortHookWrapper;
case 0x2E:
return GetCFWInfo; // DEPRECATED
case 0x32:
return SendSyncRequestHook;
case 0x3C:
return (debugOfProcess(currentProcess) != NULL) ? officialSVCs[0x3C] : (void *)Break;
case 0x59:
return SetGpuProt;
case 0x5A:
return SetWifiEnabled;
case 0x7B:
return Backdoor;
case 0x7C:
return KernelSetStateHook;
case 0x80:
return CustomBackdoor;
case 0x90:
return convertVAToPA;
case 0x91:
return flushDataCacheRange;
case 0x92:
return flushEntireDataCache;
case 0x93:
return invalidateInstructionCacheRange;
case 0x94:
return invalidateEntireInstructionCache;
case 0xA0:
return MapProcessMemoryEx;
case 0xA1:
return UnmapProcessMemoryEx;
case 0xA2:
return ControlMemoryEx;
case 0xB0:
return ControlService;
case 0xB1:
return CopyHandleWrapper;
case 0xB2:
return TranslateHandleWrapper;
default:
return (svcId <= 0x7D) ? officialSVCs[svcId] : NULL;
}
}

View File

@@ -0,0 +1,43 @@
@ 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.
.text
.arm
.balign 4
.global Backdoor
.type Backdoor, %function
Backdoor:
@ Nintendo's code
bic r1, sp, #0xff
orr r1, r1, #0xf00
add r1, r1, #0x28 @ get user stack.
ldr r2, [r1]
stmdb r2!, {sp, lr}
mov sp, r2 @ sp_svc = sp_usr. You'll get nice crashes if an interrupt or context switch occurs during svcBackdoor
blx r0
pop {r0, r1}
mov sp, r0
bx r1

View File

@@ -0,0 +1,35 @@
@ 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.
.text
.arm
.balign 4
.global Break
.type Break, %function
Break:
bic r0, sp, #0xf00
bic r0, #0xff
add r0, #0x1000 @ get page context top
bkpt 0xffff

View File

@@ -0,0 +1,56 @@
/*
* 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 "svc/ConnectToPort.h"
#include "memory.h"
#include "ipc.h"
Result ConnectToPortHook(Handle *out, const char *name)
{
char portName[12] = {0};
Result res = 0;
if(name != NULL)
{
s32 nb = usrToKernelStrncpy(portName, name, 12);
if(nb < 0)
return 0xD9001814;
else if(nb == 12 && portName[11] != 0)
return 0xE0E0181E;
}
res = ConnectToPort(out, name);
if(res != 0)
return res;
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KClientSession *clientSession = (KClientSession *)KProcessHandleTable__ToKAutoObject(handleTable, *out);
if(clientSession != NULL)
{
SessionInfo_Add(clientSession->parentSession, portName);
clientSession->syncObject.autoObject.vtable->DecrementReferenceCount(&clientSession->syncObject.autoObject);
}
return res;
}

View File

@@ -0,0 +1,34 @@
/*
* 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 "svc/ControlMemory.h"
Result ControlMemoryHook(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm)
{
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
return ControlMemory(addrOut, addr0, addr1, size, op, perm, idOfProcess(currentProcess) == 1);
}

View File

@@ -0,0 +1,108 @@
/*
* 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 "svc/ControlService.h"
#include "memory.h"
#include "ipc.h"
Result ControlService(ServiceOp op, u32 varg1, u32 varg2)
{
Result res = 0;
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
switch(op)
{
case SERVICEOP_GET_NAME:
{
KSession *session = NULL;
SessionInfo *info = NULL;
KAutoObject *obj = KProcessHandleTable__ToKAutoObject(handleTable, (Handle)varg2);
if(obj == NULL)
return 0xD8E007F7; // invalid handle
else if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
obj->vtable->GetClassToken(&tok, obj);
if(tok.flags == 0x95)
session = ((KServerSession *)obj)->parentSession;
else if(tok.flags == 0xA5)
session = ((KClientSession *)obj)->parentSession;
}
else
{ // not the exact same tests but it should work
if(strcmp(obj->vtable->GetClassName(obj), "KServerSession") == 0)
session = ((KServerSession *)obj)->parentSession;
else if(strcmp(obj->vtable->GetClassName(obj), "KClientSession") == 0)
session = ((KClientSession *)obj)->parentSession;
}
if(session != NULL)
info = SessionInfo_Lookup(session);
if(info == NULL)
res = 0xD8E007F7;
else
{
// names are limited to 11 characters (for ports)
// kernelToUsrStrncpy doesn't clear trailing bytes
char name[12] = { 0 };
strncpy(name, info->name, 12);
res = kernelToUsrMemcpy8((void *)varg1, name, strlen(name) + 1) ? 0 : 0xE0E01BF5;
}
obj->vtable->DecrementReferenceCount(obj);
return res;
}
case SERVICEOP_STEAL_CLIENT_SESSION:
{
char name[12] = { 0 };
SessionInfo *info = NULL;
if(name != NULL)
{
s32 nb = usrToKernelStrncpy(name, (const char *)varg2, 12);
if(nb < 0)
return 0xD9001814;
else if(nb == 12 && name[11] != 0)
return 0xE0E0181E;
}
info = SessionInfo_FindFirst(name);
if(info == NULL)
return 0x9401BFE; // timeout (the wanted service is likely not initalized)
else
{
Handle out;
res = createHandleForThisProcess(&out, &info->session->clientSession.syncObject.autoObject);
return (res != 0) ? res : (kernelToUsrMemcpy32((u32 *)varg1, (u32 *)&out, 4) ? 0 : (Result)0xE0E01BF5);
}
}
default:
return 0xF8C007F4;
}
}

View File

@@ -0,0 +1,76 @@
/*
* 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 "svc/CopyHandle.h"
#include "memory.h"
Result CopyHandle(Handle *outHandle, Handle outProcessHandle, Handle inHandle, Handle inProcessHandle)
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KProcess *inProcess, *outProcess;
Result res;
if(inProcessHandle == CUR_PROCESS_HANDLE)
{
inProcess = currentCoreContext->objectContext.currentProcess;
KAutoObject__AddReference((KAutoObject *)inProcess);
}
else
inProcess = KProcessHandleTable__ToKProcess(handleTable, inProcessHandle);
if(inProcess == NULL)
return 0xD8E007F7; // invalid handle
if(outProcessHandle == CUR_PROCESS_HANDLE)
{
outProcess = currentCoreContext->objectContext.currentProcess;
KAutoObject__AddReference((KAutoObject *)outProcess);
}
else
outProcess = KProcessHandleTable__ToKProcess(handleTable, outProcessHandle);
if(outProcess == NULL)
{
((KAutoObject *)inProcess)->vtable->DecrementReferenceCount((KAutoObject *)inProcess);
return 0xD8E007F7; // invalid handle
}
KAutoObject *obj = KProcessHandleTable__ToKAutoObject(handleTableOfProcess(inProcess), inHandle);
if(obj == NULL)
{
((KAutoObject *)inProcess)->vtable->DecrementReferenceCount((KAutoObject *)inProcess);
((KAutoObject *)outProcess)->vtable->DecrementReferenceCount((KAutoObject *)outProcess);
return 0xD8E007F7; // invalid handle
}
res = createHandleForProcess(outHandle, outProcess, obj);
obj->vtable->DecrementReferenceCount(obj);
((KAutoObject *)inProcess)->vtable->DecrementReferenceCount((KAutoObject *)inProcess);
((KAutoObject *)outProcess)->vtable->DecrementReferenceCount((KAutoObject *)outProcess);
return res;
}

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.
*/
#include "svc/GetCFWInfo.h"
// DEPRECATED
Result GetCFWInfo(CfwInfo *out)
{
return kernelToUsrMemcpy8(out, &cfwInfo, 16) ? 0 : 0xE0E01BF5;
}

View File

@@ -0,0 +1,94 @@
/*
* 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 "svc/GetProcessInfo.h"
#include "memory.h"
Result GetProcessInfoHook(s64 *out, Handle processHandle, u32 type)
{
Result res = 0;
if(type >= 0x10000)
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KProcess *process;
if(processHandle == CUR_PROCESS_HANDLE)
{
process = currentCoreContext->objectContext.currentProcess;
KAutoObject__AddReference((KAutoObject *)process);
}
else
process = KProcessHandleTable__ToKProcess(handleTable, processHandle);
if(process == NULL)
return 0xD8E007F7; // invalid handle
switch(type)
{
case 0x10000:
memcpy(out, codeSetOfProcess(process)->processName, 8);
break;
case 0x10001:
*(u64 *)out = codeSetOfProcess(process)->titleId;
break;
case 0x10002:
*out = codeSetOfProcess(process)->nbTextPages << 12;
break;
case 0x10003:
*out = codeSetOfProcess(process)->nbRodataPages << 12;
break;
case 0x10004:
*out = codeSetOfProcess(process)->nbRwPages << 12;
break;
case 0x10005:
*out = (s64)(u64)(u32)codeSetOfProcess(process)->textSection.section.loadAddress;
break;
case 0x10006:
*out = (s64)(u64)(u32)codeSetOfProcess(process)->rodataSection.section.loadAddress;
break;
case 0x10007:
*out = (s64)(u64)(u32)codeSetOfProcess(process)->dataSection.section.loadAddress;
break;
case 0x10008:
*out = (isN3DS ? hwInfoOfProcess(process)->N3DS.translationTableBase :
(kernelVersion >= SYSTEM_VERSION(2, 44, 6)
? hwInfoOfProcess(process)->O3DS8x.translationTableBase
: hwInfoOfProcess(process)->O3DSPre8x.translationTableBase)
) & ~((1 << (14 - TTBCR)) - 1);
break;
default:
res = 0xD8E007ED; // invalid enum value
break;
}
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
}
else
res = GetProcessInfo(out, processHandle, type);
return res;
}

View File

@@ -0,0 +1,123 @@
/*
* 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 "svc/GetSystemInfo.h"
#include "utils.h"
#include "ipc.h"
#include "synchronization.h"
Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
{
Result res = 0;
switch(type)
{
case 0x10000:
{
switch(param)
{
case 0:
*out = SYSTEM_VERSION(cfwInfo.versionMajor, cfwInfo.versionMinor, cfwInfo.versionBuild);
break;
case 1:
*out = cfwInfo.commitHash;
break;
case 2:
*out = cfwInfo.config;
break;
case 3: // isRelease
*out = cfwInfo.flags & 1;
break;
case 4: // isN3DS
*out = (cfwInfo.flags >> 4) & 1;
break;
case 5: // isSafeMode
*out = (cfwInfo.flags >> 5) & 1;
break;
case 6: // isSdMode
*out = (cfwInfo.flags >> 6) & 1;
break;
default:
res = 0xF8C007F4; // not implemented
break;
}
break;
}
case 0x10001: // N3DS-related info
{
if(isN3DS)
{
switch(param)
{
case 0: // current clock rate
*out = (((CFG11_MPCORE_CLKCNT >> 1) & 3) + 1) * 268;
break;
case 1: // higher clock rate
*out = (((CFG11_MPCORE_CFG >> 2) & 1) + 2) * 268;
break;
case 2: // L2C enabled status
*out = L2C_CTRL & 1;
break;
default:
res = 0xF8C007F4;
break;
}
}
else
res = 0xF8C007F4;
break;
}
case 0x10002: // MMU config (cached values from booting)
{
switch(param)
{
case 0:
*out = TTBCR;
break;
default:
{
if((u32)param <= getNumberOfCores())
*out = L1MMUTableAddrs[param - 1];
else
res = 0xF8C007F4;
break;
}
}
break;
}
default:
GetSystemInfo(out, type, param);
break;
}
return res;
}

View File

@@ -0,0 +1,60 @@
/*
* 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 "svc/GetThreadInfo.h"
#include "memory.h"
Result GetThreadInfoHook(s64 *out, Handle threadHandle, u32 type)
{
Result res = 0;
if(type == 0x10000) // Get TLS
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KThread *thread;
if(threadHandle == CUR_THREAD_HANDLE)
{
thread = currentCoreContext->objectContext.currentThread;
KAutoObject__AddReference(&thread->syncObject.autoObject);
}
else
thread = KProcessHandleTable__ToKThread(handleTable, threadHandle);
if(thread == NULL)
return 0xD8E007F7; // invalid handle
*out = (s64)(u64)(u32)thread->threadLocalStorage;
KAutoObject *obj = (KAutoObject *)thread;
obj->vtable->DecrementReferenceCount(obj);
}
else
res = GetThreadInfo(out, threadHandle, type);
return res;
}

View File

@@ -0,0 +1,149 @@
/*
* 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 "svc/KernelSetState.h"
#include "synchronization.h"
#include "ipc.h"
#include "memory.h"
#define MAX_DEBUG 3
static u32 nbEnabled = 0;
static u32 maskedPids[MAX_DEBUG];
static u32 masks[MAX_DEBUG][8] = {0};
bool shouldSignalSyscallDebugEvent(KProcess *process, u8 svcId)
{
u32 pid = idOfProcess(process);
u32 id;
for(id = 0; id < nbEnabled && maskedPids[id] != pid; id++);
if(id == MAX_DEBUG)
return false;
else
return ((masks[id][svcId / 32] >> (31 - (svcId % 32))) & 1) != 0;
}
Result SetSyscallDebugEventMask(u32 pid, bool enable, const u32 *mask)
{
static KRecursiveLock syscallDebugEventMaskLock = { NULL };
u32 tmpMask[8];
if(enable && nbEnabled == MAX_DEBUG)
return 0xC86018FF; // Out of resource (255)
if(enable && !usrToKernelMemcpy8(&tmpMask, mask, 32))
return 0xE0E01BF5;
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&syscallDebugEventMaskLock);
if(enable)
{
maskedPids[nbEnabled] = pid;
memcpy(&masks[nbEnabled++], tmpMask, 32);
}
else
{
u32 id;
for(id = 0; id < nbEnabled && maskedPids[id] != pid; id++);
if(id == nbEnabled)
{
KRecursiveLock__Unlock(&syscallDebugEventMaskLock);
KRecursiveLock__Unlock(criticalSectionLock);
return 0xE0E01BFD; // out of range (it's not fully technically correct but meh)
}
for(u32 i = id; i < nbEnabled - 1; i++)
{
maskedPids[i] = maskedPids[i + 1];
memcpy(&masks[i], &masks[i + 1], 32);
}
maskedPids[--nbEnabled] = 0;
memset(&masks[nbEnabled], 0, 32);
}
KRecursiveLock__Unlock(&syscallDebugEventMaskLock);
KRecursiveLock__Unlock(criticalSectionLock);
return 0;
}
Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
{
Result res = 0;
switch(type)
{
case 0x10000:
{
do
{
__ldrex((s32 *)&rosalinaState);
}
while(__strex((s32 *)&rosalinaState, (s32)(rosalinaState ^ varg1)));
if(rosalinaState & 2)
hasStartedRosalinaNetworkFuncsOnce = true;
break;
}
case 0x10001:
{
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&processLangemuLock);
u32 i;
for(i = 0; i < 0x40 && processLangemuAttributes[i].titleId != 0ULL; i++);
if(i < 0x40)
{
processLangemuAttributes[i].titleId = ((u64)varg3 << 32) | (u32)varg2;
processLangemuAttributes[i].state = (u8)(varg1 >> 24);
processLangemuAttributes[i].country = (u8)(varg1 >> 16);
processLangemuAttributes[i].language = (u8)(varg1 >> 8);
processLangemuAttributes[i].region = (u8)(varg1 >> 4);
processLangemuAttributes[i].mask = (u8)(varg1 & 0xf);
}
else
res = 0xD8609013;
KRecursiveLock__Unlock(&processLangemuLock);
KRecursiveLock__Unlock(criticalSectionLock);
break;
}
case 0x10002:
{
res = SetSyscallDebugEventMask(varg1, (bool)varg2, (const u32 *)varg3);
break;
}
default:
{
res = KernelSetState(type, varg1, varg2, varg3);
break;
}
}
return res;
}

View File

@@ -0,0 +1,44 @@
/*
* 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 "svc/MapProcessMemoryEx.h"
Result MapProcessMemoryEx(Handle processHandle, void *dst, void *src, u32 size)
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KProcessHwInfo *currentHwInfo = hwInfoOfProcess(currentCoreContext->objectContext.currentProcess);
KProcess *process = KProcessHandleTable__ToKProcess(handleTable, processHandle);
if(process == NULL)
return 0xD8E007F7;
Result res = KProcessHwInfo__MapProcessMemory(currentHwInfo, hwInfoOfProcess(process), dst, src, size >> 12);
KAutoObject *obj = (KAutoObject *)process;
obj->vtable->DecrementReferenceCount(obj);
return res;
}

View File

@@ -0,0 +1,237 @@
/*
* 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 "svc/SendSyncRequest.h"
#include "memory.h"
#include "ipc.h"
Result SendSyncRequestHook(Handle handle)
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KClientSession *clientSession = (KClientSession *)KProcessHandleTable__ToKAutoObject(handleTable, handle);
u32 *cmdbuf = (u32 *)((u8 *)currentCoreContext->objectContext.currentThread->threadLocalStorage + 0x80);
bool skip = false;
Result res = 0;
bool isValidClientSession = false;
if(clientSession != NULL && kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
clientSession->syncObject.autoObject.vtable->GetClassToken(&tok, &clientSession->syncObject.autoObject);
isValidClientSession = tok.flags == 0xA5;
}
else if(clientSession != NULL) // not the exact same test but it should work
isValidClientSession = strcmp(clientSession->syncObject.autoObject.vtable->GetClassName(&clientSession->syncObject.autoObject), "KClientSession");
if(isValidClientSession)
{
switch (cmdbuf[0])
{
case 0x10042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:pm") == 0)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;
}
else if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
{
cmdbuf[0] = 0x10040;
cmdbuf[1] = 0;
skip = true;
}
break;
}
case 0x10082:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:u") == 0 || strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk2
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
case 0x10800:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "err:f") == 0) // Throw
skip = doErrfThrowHook(cmdbuf);
break;
}
case 0x20000:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:u") == 0 || strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // SecureInfoGetRegion
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
case 0x20002:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
{
cmdbuf[0] = 0x20040;
cmdbuf[1] = 0;
skip = true;
}
break;
}
case 0x50100:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:") == 0)
{
char name[9] = { 0 };
memcpy(name, cmdbuf + 1, 8);
skip = true;
res = SendSyncRequest(handle);
if(res == 0)
{
KClientSession *outClientSession;
outClientSession = (KClientSession *)KProcessHandleTable__ToKAutoObject(handleTable, (Handle)cmdbuf[3]);
if(outClientSession != NULL)
{
SessionInfo_Add(outClientSession->parentSession, name);
outClientSession->syncObject.autoObject.vtable->DecrementReferenceCount(&outClientSession->syncObject.autoObject);
}
}
}
break;
}
case 0x80040:
{
if(!hasStartedRosalinaNetworkFuncsOnce)
break;
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
skip = info != NULL && strcmp(info->name, "ndm:u") == 0; // SuspendScheduler
if(skip)
cmdbuf[1] = 0;
break;
}
case 0x90000:
{
if(!hasStartedRosalinaNetworkFuncsOnce)
break;
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "ndm:u") == 0) // ResumeScheduler
{
cmdbuf[0] = 0x90040;
cmdbuf[1] = 0;
skip = true;
}
break;
}
case 0x4010042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:pm") == 0)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;
}
break;
}
case 0x4010082:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk4
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
case 0x4020082:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk8
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
case 0x8010082:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk4
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
case 0x8020082:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "cfg:i") == 0) // GetConfigInfoBlk8
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
case 0x4060000:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); // SecureInfoGetRegion
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0))
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
case 0x8160000:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); // SecureInfoGetRegion
if(info != NULL && strcmp(info->name, "cfg:i") == 0)
skip = doLangEmu(&res, handle, cmdbuf);
break;
}
}
}
if(clientSession != NULL)
clientSession->syncObject.autoObject.vtable->DecrementReferenceCount(&clientSession->syncObject.autoObject);
res = skip ? res : SendSyncRequest(handle);
return res;
}

View File

@@ -0,0 +1,32 @@
/*
* 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 "svc/SetGpuProt.h"
Result SetGpuProt(bool prot UNUSED)
{
return 0;
}

View File

@@ -0,0 +1,35 @@
/*
* 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 "svc/SetWifiEnabled.h"
void SetWifiEnabled(bool enable)
{
if(enable)
CFG11_WIFICNT |= 1;
else
CFG11_WIFICNT &= ~1;
}

View File

@@ -0,0 +1,70 @@
/*
* 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 "svc/TranslateHandle.h"
#include "memory.h"
Result TranslateHandle(u32 *outKAddr, char *outClassName, Handle handle)
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KAutoObject *obj;
Result res;
const char *name;
if(handle == CUR_THREAD_HANDLE)
{
obj = (KAutoObject *)currentCoreContext->objectContext.currentProcess;
KAutoObject__AddReference(obj);
}
else if(handle == CUR_PROCESS_HANDLE)
{
obj = (KAutoObject *)currentCoreContext->objectContext.currentProcess;
KAutoObject__AddReference(obj);
}
else
obj = KProcessHandleTable__ToKAutoObject(handleTable, handle);
if(obj == NULL)
return 0xD8E007F7; // invalid handle
if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
obj->vtable->GetClassToken(&tok, obj);
name = tok.name;
}
else
name = obj->vtable->GetClassName(obj);
if(name == NULL) // shouldn't happen
name = "KAutoObject";
*outKAddr = (u32)obj;
res = kernelToUsrMemcpy8(outClassName, name, strlen(name) + 1) ? 0 : 0xE0E01BF5;
obj->vtable->DecrementReferenceCount(obj);
return res;
}

View File

@@ -0,0 +1,39 @@
/*
* 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 "svc/MapProcessMemoryEx.h"
Result UnmapProcessMemoryEx(Handle processHandle UNUSED, void *dst, u32 size)
{
KProcessHwInfo *currentHwInfo = hwInfoOfProcess(currentCoreContext->objectContext.currentProcess);
Result res = KProcessHwInfo__UnmapProcessMemory(currentHwInfo, dst, size >> 12);
invalidateEntireInstructionCache();
flushEntireDataCache();
return res;
}

View File

@@ -0,0 +1,85 @@
@ 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.
.text
.arm
.balign 4
.macro GEN_GETINFO_WRAPPER, name
.global Get\name\()InfoHookWrapper
.type Get\name\()InfoHookWrapper, %function
Get\name\()InfoHookWrapper:
push {r12, lr}
sub sp, #8
mov r0, sp
bl Get\name\()InfoHook
pop {r1, r2, r12, pc}
.endm
GEN_GETINFO_WRAPPER System
GEN_GETINFO_WRAPPER Process
GEN_GETINFO_WRAPPER Thread
.macro GEN_OUT1_WRAPPER, name
.global \name\()Wrapper
.type \name\()Wrapper, %function
\name\()Wrapper:
push {lr}
sub sp, #4
mov r0, sp
bl \name
pop {r1, pc}
.endm
GEN_OUT1_WRAPPER ConnectToPortHook
GEN_OUT1_WRAPPER CopyHandle
GEN_OUT1_WRAPPER TranslateHandle
.global ControlMemoryHookWrapper
.type ControlMemoryHookWrapper, %function
ControlMemoryHookWrapper:
push {lr}
sub sp, #12
stmia sp, {r0, r4}
add r0, sp, #8
bl ControlMemoryHook
ldr r1, [sp, #8]
add sp, #12
pop {pc}
.global ControlMemoryEx
.type ControlMemoryEx, %function
ControlMemoryEx:
push {lr}
sub sp, #8
cmp r5, #0
movne r5, #1
push {r0, r4, r5}
add r0, sp, #12
ldr r12, =ControlMemory
ldr r12, [r12]
blx r12
ldr r1, [sp, #12]
add sp, #20
pop {pc}

View File

@@ -0,0 +1,127 @@
@ 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.
.text
.arm
.balign 4
.global svcHandler
.type svcHandler, %function
svcHandler:
srsdb sp!, #0x13
stmfd sp, {r8-r11, sp, lr}^
sub sp, #0x18
mrs r9, spsr
ands r9, #0x20
ldrneb r9, [lr, #-2]
ldreqb r9, [lr, #-4]
mov lr, #0 @ do stuff as if the "allow debug" flag is always set
push {r0-r7, r12, lr}
mov r10, #1
strb r9, [sp, #0x58+3] @ page end - 0xb8 + 3: svc being handled
strb r10, [sp, #0x58+1] @ page end - 0xb8 + 1: "allow debug" flag
@ sp = page end - 0x110
add r0, sp, #0x110 @ page end
bl svcHook
cpsid i
mov r8, r0
ldmfd sp, {r0-r7, r12, lr}
cmp r8, #0
beq _fallback @ invalid svc, or svc 0xff (stop point)
_handled_svc: @ unused label, just here for formatting
push {r0-r12, lr}
add r0, sp, #0x148
cpsie i
bl signalSvcEntry
cpsid i
pop {r0-r12, lr}
cpsie i
blx r8
cpsid i
ldrb lr, [sp, #0x58+0] @ page end - 0xb8 + 0: scheduling flags
b _fallback_end
_fallback:
mov r0, r9
ldr r8, =svcFallbackHandler
ldr r8, [r8]
blx r8
mov lr, #0
_fallback_end:
ldr r8, [sp, #0x24] @ page_end - 0xec: saved lr (see above) : should reload regs
cmp r8, #0
addeq sp, #0x24
popne {r0-r7, r12}
add sp, #4
cmp r9, #0xff
beq _no_signal_return
push {r0-r7, r12, lr}
add r0, sp, #0x110 @ page end
cpsie i
bl signalSvcReturn
cpsid i
pop {r0-r7, r12}
add sp, #4
_no_signal_return:
mov r8, #0
strb r8, [sp, #0x30+3] @ page_end - 0xb8 + 3: svc being handled
_svc_finished:
ldmfd sp, {r8-r11, sp, lr}^
cmp lr, #0
bne _postprocess_svc
_svc_return:
add sp, #0x18
rfefd sp! @ return to user mode
_postprocess_svc:
mov lr, #0
push {r0-r7, r12, lr}
push {r0-r3}
ldr r0, =PostprocessSvc
ldr r0, [r0]
blx r0
pop {r0-r3}
ldrb lr, [sp, #0x58+0] @ page end - 0xb8 + 0: scheduling flags
ldr r8, [sp, #0x24] @ page_end - 0xec: saved lr (see above) : should reload regs
cmp r8, #0
addeq sp, #0x24
popne {r0-r7, r12}
add sp, #4
b _svc_finished

View File

@@ -0,0 +1,41 @@
/*
* 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 "synchronization.h"
#include "utils.h"
#include "kernel.h"
extern SGI0Handler_t SGI0Handler;
void executeFunctionOnCores(SGI0Handler_t handler, u8 targetList, u8 targetListFilter)
{
u32 coreID = getCurrentCoreID();
SGI0Handler = handler;
if(targetListFilter == 0 && (targetListFilter & (1 << coreID)) != 0)
__asm__ volatile("cpsie i"); // make sure interrupts aren't masked
MPCORE_GID_SGI = (targetListFilter << 24) | (targetList << 16) | 0;
}

View File

@@ -0,0 +1,139 @@
@ 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.
.text
.arm
.balign 4
.global convertVAToPA
.type convertVAToPA, %function
convertVAToPA:
mov r3, r1
mov r1, #0xf00
orr r1, #0xff
and r2, r0, r1
bic r0, r1
cmp r3, #1
beq _convertVAToPA_write_check
_convertVAToPA_read_check:
mcr p15, 0, r0, c7, c8, 0 @ VA to PA translation with privileged read permission check
b _convertVAToPA_end_check
_convertVAToPA_write_check:
mcr p15, 0, r0, c7, c8, 1 @ VA to PA translation with privileged write permission check
_convertVAToPA_end_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
.global flushEntireDataCache
.type flushEntireDataCache, %function
flushEntireDataCache:
mvn r1, #0 @ this is translated to a full cache flush
ldr r12, =flushDataCacheRange
ldr r12, [r12]
bx r12
.global invalidateEntireInstructionCache
.type invalidateEntireInstructionCache, %function
invalidateEntireInstructionCache:
mvn r1, #0 @ this is translated to a full cache flush
ldr r12, =invalidateInstructionCacheRange
ldr r12, [r12]
bx r12
.global KObjectMutex__Acquire
.type KObjectMutex__Acquire, %function
KObjectMutex__Acquire:
ldr r1, =0xFFFF9000 @ current thread addr
ldr r1, [r1]
ldrex r2, [r0]
cmp r2, #0
strexeq r3, r1, [r0] @ store current thread
strexne r3, r2, [r0] @ stored thread != NULL, no change
cmpeq r3, #0
bxeq lr
ldr r12, =KObjectMutex__WaitAndAcquire
ldr r12, [r12]
bx r12
.global KObjectMutex__Release
.type KObjectMutex__Release, %function
KObjectMutex__Release:
mov r1, #0
str r1, [r0]
ldrh r1, [r0, #4]
cmp r1, #0
bxle lr
ldr r12, =KObjectMutex__ErrorOccured
ldr r12, [r12]
blx r12
bx lr
.global safecpy
.type safecpy, %function
safecpy:
push {r4, lr}
mov r3, #0
movs r12, #1
_safecpy_loop:
ldrb r4, [r1, r3]
cmp r12, #0
beq _safecpy_loop_end
strb r4, [r0, r3]
add r3, #1
cmp r3, r2
blo _safecpy_loop
_safecpy_loop_end:
mov r0, r3
pop {r4, pc}
_safecpy_end:
.section .rodata
.global safecpy_sz
safecpy_sz: .word _safecpy_end - safecpy
.bss
.balign 4
.global SGI0Handler
SGI0Handler: .word 0 @ see synchronization.c
.balign 4
.section .data
.balign 4
_customInterruptEventObj: .word SGI0Handler
.global customInterruptEvent
customInterruptEvent: .word _customInterruptEventObj