2017-06-05 02:02:04 +02:00
|
|
|
/*
|
|
|
|
* This file is part of Luma3DS
|
2020-04-25 14:26:21 +02:00
|
|
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
2017-06-05 02:02:04 +02:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2018-05-24 00:55:38 +02:00
|
|
|
#include <string.h>
|
2017-06-05 02:02:04 +02:00
|
|
|
#include "utils.h"
|
|
|
|
#include "globals.h"
|
|
|
|
#include "synchronization.h"
|
|
|
|
#include "fatalExceptionHandlers.h"
|
|
|
|
#include "svc.h"
|
|
|
|
#include "svc/ConnectToPort.h"
|
|
|
|
#include "svcHandler.h"
|
|
|
|
|
2020-04-28 03:39:57 +02:00
|
|
|
#define K11EXT_VA 0x70000000
|
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
struct KExtParameters
|
2017-06-05 02:02:04 +02:00
|
|
|
{
|
2017-06-13 02:00:41 +02:00
|
|
|
u32 basePA;
|
2020-05-18 02:15:44 +02:00
|
|
|
u32 stolenSystemMemRegionSize;
|
2017-06-13 02:00:41 +02:00
|
|
|
void *originalHandlers[4];
|
|
|
|
u32 L1MMUTableAddrs[4];
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-05-18 21:48:54 +02:00
|
|
|
volatile bool done;
|
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
CfwInfo cfwInfo;
|
|
|
|
} kExtParameters = { .basePA = 0x12345678 }; // place this in .data
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-04-28 03:39:57 +02:00
|
|
|
static ALIGN(1024) u32 g_L2Table[256] = {0};
|
2018-06-07 16:44:29 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
void relocateAndSetupMMU(u32 coreId, u32 *L1Table)
|
2017-06-05 02:02:04 +02:00
|
|
|
{
|
2020-04-28 03:39:57 +02:00
|
|
|
struct KExtParameters *p0 = (struct KExtParameters *)((u32)&kExtParameters - K11EXT_VA + 0x18000000);
|
|
|
|
struct KExtParameters *p = (struct KExtParameters *)((u32)&kExtParameters - K11EXT_VA + p0->basePA);
|
|
|
|
u32 *L2Table = (u32 *)((u32)g_L2Table - K11EXT_VA + p0->basePA);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
if(coreId == 0)
|
|
|
|
{
|
|
|
|
// Relocate ourselves, and clear BSS
|
2018-05-25 23:27:50 +02:00
|
|
|
// This is only OK because the jumps will be relative & there's no mode switch...
|
2017-06-13 02:00:41 +02:00
|
|
|
memcpy((void *)p0->basePA, (const void *)0x18000000, __bss_start__ - __start__);
|
2018-05-24 00:55:38 +02:00
|
|
|
memset((u32 *)(p0->basePA + (__bss_start__ - __start__)), 0, __bss_end__ - __bss_start__);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-04-28 03:39:57 +02:00
|
|
|
// Map the kernel ext at K11EXT_VA
|
2020-05-18 21:48:54 +02:00
|
|
|
// 4KB extended small pages:
|
|
|
|
// Outer Write-Through cached, No Allocate on Write, Buffered
|
|
|
|
// Inner Cached Write-Back Write-Allocate, Buffered
|
|
|
|
// This was changed at some point (8.0 maybe?), it was outer noncached before
|
2017-06-13 02:00:41 +02:00
|
|
|
for(u32 offset = 0; offset < (u32)(__end__ - __start__); offset += 0x1000)
|
2020-05-18 21:48:54 +02:00
|
|
|
L2Table[offset >> 12] = (p0->basePA + offset) | 0x596;
|
|
|
|
|
|
|
|
p0->done = true;
|
|
|
|
|
|
|
|
// DSB, Flush Prefetch Buffer (more or less "isb")
|
|
|
|
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" :: "r" (0) : "memory");
|
|
|
|
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" :: "r" (0) : "memory");
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
__asm__ __volatile__ ("sev");
|
|
|
|
}
|
2020-05-18 21:48:54 +02:00
|
|
|
else {
|
|
|
|
do
|
|
|
|
{
|
|
|
|
__asm__ __volatile__ ("wfe");
|
|
|
|
} while(!p0->done);
|
2017-06-13 02:00:41 +02:00
|
|
|
|
2020-05-18 21:48:54 +02:00
|
|
|
// DSB, Flush Prefetch Buffer (more or less "isb")
|
|
|
|
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" :: "r" (0) : "memory");
|
|
|
|
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" :: "r" (0) : "memory");
|
|
|
|
}
|
2017-06-13 02:00:41 +02:00
|
|
|
// bit31 idea thanks to SALT
|
|
|
|
// Maps physmem so that, if addr is in physmem(0, 0x30000000), it can be accessed uncached&rwx as addr|(1<<31)
|
|
|
|
u32 attribs = 0x40C02; // supersection (rwx for all) of strongly ordered memory, shared
|
|
|
|
for(u32 PA = 0; PA < 0x30000000; PA += 0x01000000)
|
|
|
|
{
|
|
|
|
u32 VA = (1 << 31) | PA;
|
|
|
|
for(u32 i = 0; i < 16; i++)
|
|
|
|
L1Table[i + (VA >> 20)] = PA | attribs;
|
|
|
|
}
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-04-28 03:39:57 +02:00
|
|
|
L1Table[K11EXT_VA >> 20] = (u32)L2Table | 1;
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
p->L1MMUTableAddrs[coreId] = (u32)L1Table;
|
2020-05-18 21:48:54 +02:00
|
|
|
|
|
|
|
// DSB, Flush Prefetch Buffer (more or less "isb")
|
|
|
|
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" :: "r" (0) : "memory");
|
|
|
|
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" :: "r" (0) : "memory");
|
2017-06-13 02:00:41 +02:00
|
|
|
}
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
void bindSGI0Hook(void)
|
|
|
|
{
|
|
|
|
if(InterruptManager__MapInterrupt(interruptManager, customInterruptEvent, 0, getCurrentCoreID(), 0, false, false) != 0)
|
|
|
|
__asm__ __volatile__ ("bkpt 0xdead");
|
2017-06-05 02:02:04 +02:00
|
|
|
}
|
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
void configHook(vu8 *cfgPage)
|
2017-06-05 02:02:04 +02:00
|
|
|
{
|
2017-06-13 02:00:41 +02:00
|
|
|
configPage = cfgPage;
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
kernelVersion = *(vu32 *)configPage;
|
2017-06-14 01:29:55 +02:00
|
|
|
*(vu32 *)(configPage + 0x40) = fcramLayout.applicationSize;
|
|
|
|
*(vu32 *)(configPage + 0x44) = fcramLayout.systemSize;
|
|
|
|
*(vu32 *)(configPage + 0x48) = fcramLayout.baseSize;
|
2017-06-13 02:00:41 +02:00
|
|
|
*isDevUnit = true; // enable debug features
|
2017-06-05 02:02:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void findUsefulSymbols(void)
|
|
|
|
{
|
|
|
|
u32 *off;
|
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
for(off = (u32 *)0xFFFF0000; *off != 0xE1A0D002; off++);
|
|
|
|
off += 3;
|
|
|
|
initFPU = (void (*) (void))off;
|
|
|
|
|
|
|
|
for(; *off != 0xE3A0A0C2; off++);
|
|
|
|
mcuReboot = (void (*) (void))--off;
|
2020-04-25 14:17:23 +02:00
|
|
|
coreBarrier = (void (*) (void))decodeArmBranch(off - 4);
|
2017-06-13 02:00:41 +02:00
|
|
|
|
|
|
|
for(off = (u32 *)originalHandlers[2]; *off != 0xE1A00009; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
svcFallbackHandler = (void (*)(u8))decodeArmBranch(off + 1);
|
2017-06-13 02:00:41 +02:00
|
|
|
for(; *off != 0xE92D000F; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
officialPostProcessSvc = (void (*)(void))decodeArmBranch(off + 1);
|
2017-06-13 02:00:41 +02:00
|
|
|
|
2020-04-25 14:17:23 +02:00
|
|
|
KProcessHandleTable__ToKProcess = (KProcess * (*)(KProcessHandleTable *, Handle))decodeArmBranch(5 + (u32 *)officialSVCs[0x76]);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-16 04:21:48 +02:00
|
|
|
for(off = (u32 *)KProcessHandleTable__ToKProcess; *off != 0xE1A00004; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KAutoObject__AddReference = (void (*)(KAutoObject *))decodeArmBranch(off + 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-16 04:21:48 +02:00
|
|
|
for(; *off != 0xE320F000; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KProcessHandleTable__ToKAutoObject = (KAutoObject * (*)(KProcessHandleTable *, Handle))decodeArmBranch(off + 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-04-25 14:17:23 +02:00
|
|
|
for(off = (u32 *)decodeArmBranch(3 + (u32 *)officialSVCs[9]); /* KThread::Terminate */ *off != 0xE5D42034; off++);
|
2017-06-05 02:02:04 +02:00
|
|
|
off -= 2;
|
|
|
|
criticalSectionLock = (KRecursiveLock *)off[2 + (off[0] & 0xFF) / 4];
|
2020-04-25 14:17:23 +02:00
|
|
|
KRecursiveLock__Lock = (void (*)(KRecursiveLock *))decodeArmBranch(off + 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
off += 4;
|
|
|
|
|
|
|
|
for(; (*off >> 16) != 0xE59F; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KRecursiveLock__Unlock = (void (*)(KRecursiveLock *))decodeArmBranch(off + 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
|
|
|
for(; *off != 0xE5C4007D; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KSynchronizationObject__Signal = (void (*)(KSynchronizationObject *, bool))decodeArmBranch(off + 3);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
|
|
|
for(off = (u32 *)officialSVCs[0x19]; *off != 0xE1A04005; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KEvent__Clear = (Result (*)(KEvent *))decodeArmBranch(off + 1);
|
2017-06-14 19:35:03 +02:00
|
|
|
for(off = (u32 *)KEvent__Clear; *off != 0xE8BD8070; off++);
|
2017-06-05 02:02:04 +02:00
|
|
|
synchronizationMutex = *(KObjectMutex **)(off + 1);
|
|
|
|
|
|
|
|
for(off = (u32 *)officialSVCs[0x24]; *off != 0xE59F004C; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
WaitSynchronization1 = (Result (*)(void *, KThread *, KSynchronizationObject *, s64))decodeArmBranch(off + 6);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-04-25 14:17:23 +02:00
|
|
|
for(off = (u32 *)decodeArmBranch(3 + (u32 *)officialSVCs[0x33]) /* OpenProcess */ ; *off != 0xE1A05000; off++);
|
|
|
|
KProcessHandleTable__CreateHandle = (Result (*)(KProcessHandleTable *, Handle *, KAutoObject *, u8))decodeArmBranch(off - 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-04-25 14:17:23 +02:00
|
|
|
for(off = (u32 *)decodeArmBranch(3 + (u32 *)officialSVCs[0x34]) /* OpenThread */; *off != 0xD9001BF7; off++);
|
2017-06-05 02:02:04 +02:00
|
|
|
threadList = *(KObjectList **)(off + 1);
|
|
|
|
|
2020-04-25 14:17:23 +02:00
|
|
|
off = (u32 *)decodeArmBranch((u32 *)officialSVCs[0x37] + 3) + 5; /* GetThreadId */
|
|
|
|
KProcessHandleTable__ToKThread = (KThread * (*)(KProcessHandleTable *, Handle))decodeArmBranch((*off >> 16) == 0xEB00 ? off : off + 2);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
for(off = (u32 *)officialSVCs[0x50]; off[0] != 0xE1A05000 || off[1] != 0xE2100102 || off[2] != 0x5A00000B; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
InterruptManager__MapInterrupt = (Result (*)(InterruptManager *, KBaseInterruptEvent *, u32, u32, u32, bool, bool))decodeArmBranch(--off);
|
2017-06-13 02:00:41 +02:00
|
|
|
interruptManager = *(InterruptManager **)(off - 4 + (off[-6] & 0xFFF) / 4);
|
2017-06-05 02:02:04 +02:00
|
|
|
for(off = (u32 *)officialSVCs[0x54]; *off != 0xE8BD8008; off++);
|
|
|
|
flushDataCacheRange = (void (*)(void *, u32))(*(u32 **)(off[1]) + 3);
|
|
|
|
|
|
|
|
for(off = (u32 *)officialSVCs[0x71]; *off != 0xE2101102; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KProcessHwInfo__MapProcessMemory = (Result (*)(KProcessHwInfo *, KProcessHwInfo *, void *, void *, u32))decodeArmBranch(off - 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-16 22:37:04 +02:00
|
|
|
// From 4.x to 6.x the pattern will match but the result will be wrong
|
2017-06-05 02:02:04 +02:00
|
|
|
for(off = (u32 *)officialSVCs[0x72]; *off != 0xE2041102; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KProcessHwInfo__UnmapProcessMemory = (Result (*)(KProcessHwInfo *, void *, u32))decodeArmBranch(off - 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
|
|
|
for(off = (u32 *)officialSVCs[0x7C]; *off != 0x03530000; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KObjectMutex__WaitAndAcquire = (void (*)(KObjectMutex *))decodeArmBranch(++off);
|
2017-06-05 02:02:04 +02:00
|
|
|
for(; *off != 0xE320F000; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
KObjectMutex__ErrorOccured = (void (*)(void))decodeArmBranch(off + 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
for(off = (u32 *)originalHandlers[4]; *off != (u32)exceptionStackTop; off++);
|
2017-06-05 02:02:04 +02:00
|
|
|
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))
|
2020-04-25 14:17:23 +02:00
|
|
|
decodeArmBranch((u32 *)officialSVCs[0x01] + 5);
|
2017-06-05 02:02:04 +02:00
|
|
|
SleepThread = (void (*)(s64))officialSVCs[0x0A];
|
|
|
|
CloseHandle = (Result (*)(Handle))officialSVCs[0x23];
|
2020-04-25 14:17:23 +02:00
|
|
|
GetHandleInfo = (Result (*)(s64 *, Handle, u32))decodeArmBranch((u32 *)officialSVCs[0x29] + 3);
|
|
|
|
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);
|
2017-06-05 02:02:04 +02:00
|
|
|
SendSyncRequest = (Result (*)(Handle))officialSVCs[0x32];
|
2020-04-25 14:17:23 +02:00
|
|
|
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);
|
2017-06-16 04:21:48 +02:00
|
|
|
UnmapProcessMemory = (Result (*)(Handle, void *, u32))officialSVCs[0x72];
|
2017-06-05 02:02:04 +02:00
|
|
|
KernelSetState = (Result (*)(u32, u32, u32, u32))((u32 *)officialSVCs[0x7C] + 1);
|
|
|
|
|
|
|
|
for(off = (u32 *)svcFallbackHandler; *off != 0xE8BD4010; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
kernelpanic = (void (*)(void))decodeArmBranch(off + 1);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
|
|
|
for(off = (u32 *)0xFFFF0000; off[0] != 0xE3A01002 || off[1] != 0xE3A00004; off++);
|
2020-04-25 14:17:23 +02:00
|
|
|
SignalDebugEvent = (Result (*)(DebugEventType type, u32 info, ...))decodeArmBranch(off + 2);
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
for(; *off != 0x96007F9; off++);
|
2017-06-05 02:02:04 +02:00
|
|
|
isDevUnit = *(bool **)(off - 1);
|
|
|
|
|
|
|
|
///////////////////////////////////////////
|
|
|
|
|
|
|
|
// Shitty/lazy heuristic but it works on even 4.5, so...
|
2017-06-13 02:00:41 +02:00
|
|
|
u32 textStart = ((u32)originalHandlers[2]) & ~0xFFFF;
|
|
|
|
u32 rodataStart = (u32)(interruptManager->N3DS.privateInterrupts[1][0x1D].interruptEvent->vtable) & ~0xFFF;
|
2017-06-05 02:02:04 +02:00
|
|
|
u32 textSize = rodataStart - textStart;
|
2017-06-08 21:35:41 +02:00
|
|
|
for(off = (u32 *)textStart; off < (u32 *)(textStart + textSize - 12); off++)
|
2017-06-05 02:02:04 +02:00
|
|
|
{
|
|
|
|
if(off[0] == 0xE5D13034 && off[1] == 0xE1530002)
|
|
|
|
KScheduler__AdjustThread = (void (*)(KScheduler *, KThread *, u32))off;
|
|
|
|
else if(off[0] == (u32)interruptManager && off[1] == (u32)¤tCoreContext->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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-14 19:35:03 +02:00
|
|
|
void main(FcramLayout *layout, KCoreContext *ctxs)
|
2017-06-05 02:02:04 +02:00
|
|
|
{
|
2017-06-13 02:00:41 +02:00
|
|
|
struct KExtParameters *p = &kExtParameters;
|
|
|
|
u32 TTBCR_;
|
|
|
|
s64 nb;
|
2017-06-05 02:02:04 +02:00
|
|
|
|
2020-05-18 02:15:44 +02:00
|
|
|
cfwInfo = p->cfwInfo;
|
|
|
|
kextBasePa = p->basePA;
|
|
|
|
stolenSystemMemRegionSize = p->stolenSystemMemRegionSize;
|
|
|
|
|
|
|
|
u32 kextSize = (u32)(__end__ - __start__);
|
|
|
|
layout->systemSize -= stolenSystemMemRegionSize;
|
|
|
|
layout->baseAddr = layout->baseAddr - stolenSystemMemRegionSize + kextSize;
|
|
|
|
layout->baseSize = layout->baseSize + stolenSystemMemRegionSize - kextSize;
|
2017-06-14 01:29:55 +02:00
|
|
|
fcramLayout = *layout;
|
2017-06-14 19:35:03 +02:00
|
|
|
coreCtxs = ctxs;
|
2017-06-14 01:29:55 +02:00
|
|
|
|
2017-06-14 19:35:03 +02:00
|
|
|
__asm__ __volatile__("mrc p15, 0, %0, c2, c0, 2" : "=r"(TTBCR_));
|
2017-06-13 02:00:41 +02:00
|
|
|
TTBCR = TTBCR_;
|
2017-06-05 02:02:04 +02:00
|
|
|
isN3DS = getNumberOfCores() == 4;
|
|
|
|
memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16);
|
|
|
|
exceptionStackTop = (u32 *)0xFFFF2000 + (1 << (32 - TTBCR - 20));
|
|
|
|
|
2017-06-13 02:00:41 +02:00
|
|
|
memcpy(originalHandlers + 1, p->originalHandlers, 16);
|
|
|
|
void **arm11SvcTable = (void**)originalHandlers[2];
|
|
|
|
while(*arm11SvcTable != NULL) arm11SvcTable++; //Look for SVC0 (NULL)
|
|
|
|
memcpy(officialSVCs, arm11SvcTable, 4 * 0x7E);
|
|
|
|
|
2017-06-05 02:02:04 +02:00
|
|
|
findUsefulSymbols();
|
2017-06-13 02:00:41 +02:00
|
|
|
|
|
|
|
GetSystemInfo(&nb, 26, 0);
|
|
|
|
nbSection0Modules = (u32)nb;
|
2017-06-05 02:02:04 +02:00
|
|
|
|
|
|
|
rosalinaState = 0;
|
|
|
|
hasStartedRosalinaNetworkFuncsOnce = false;
|
|
|
|
}
|