mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
147 lines
3.2 KiB
C
147 lines
3.2 KiB
C
// Copyright 2018 plutoo
|
|
#include <switch.h>
|
|
|
|
static bool g_isNso = false;
|
|
static Handle g_mainThreadHandle = INVALID_HANDLE;
|
|
static LoaderReturnFn g_loaderRetAddr = NULL;
|
|
static void* g_overrideHeapAddr = NULL;
|
|
static u64 g_overrideHeapSize = 0;
|
|
static u64 g_overrideArgc = 0;
|
|
static void* g_overrideArgv = NULL;
|
|
static u64 g_syscallHints[0x80/8];
|
|
|
|
typedef struct {
|
|
u32 Key;
|
|
u32 Flags;
|
|
u64 Value[2];
|
|
} ConfigEntry;
|
|
|
|
enum {
|
|
IsMandatory = BIT(0),
|
|
};
|
|
|
|
enum {
|
|
EntryType_EndOfList=0,
|
|
EntryType_MainThreadHandle=1,
|
|
EntryType_LoaderReturnAddr=2,
|
|
EntryType_OverrideHeap=3,
|
|
EntryType_OverrideService=4,
|
|
EntryType_Argv=5,
|
|
EntryType_SyscallAvailableHint=6,
|
|
EntryType_AppletType=7
|
|
};
|
|
|
|
void envParse(void* ctx, Handle main_thread)
|
|
{
|
|
if (main_thread != INVALID_HANDLE)
|
|
{
|
|
g_mainThreadHandle = main_thread;
|
|
g_isNso = true;
|
|
|
|
// For NSO we assume kernelhax thus access to all syscalls.
|
|
memset((void*) &g_syscallHints, 0xFF, sizeof(g_syscallHints));
|
|
|
|
return;
|
|
}
|
|
|
|
ConfigEntry* ent = ctx;
|
|
|
|
while (ent->Key != EntryType_EndOfList)
|
|
{
|
|
switch (ent->Key)
|
|
{
|
|
case EntryType_MainThreadHandle:
|
|
g_mainThreadHandle = ent->Value[0];
|
|
break;
|
|
|
|
case EntryType_LoaderReturnAddr:
|
|
g_loaderRetAddr = (void*) ent->Value[0];
|
|
break;
|
|
|
|
case EntryType_OverrideHeap:
|
|
g_overrideHeapAddr = (void*) ent->Value[0];
|
|
g_overrideHeapSize = ent->Value[1];
|
|
break;
|
|
|
|
case EntryType_OverrideService:
|
|
smAddOverrideHandle(ent->Value[0], ent->Value[1]);
|
|
break;
|
|
|
|
case EntryType_Argv:
|
|
g_overrideArgc = ent->Value[0];
|
|
g_overrideArgv = (void*) ent->Value[1];
|
|
break;
|
|
|
|
case EntryType_SyscallAvailableHint: {
|
|
int i, j;
|
|
|
|
for (i=0; i<2; i++) for (j=0; j<8; j++)
|
|
{
|
|
u8 svc = ent->Value[i] >> (8*j);
|
|
|
|
if (svc < 0x80)
|
|
g_syscallHints[svc/64] |= 1llu << (svc%64);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case EntryType_AppletType:
|
|
// TODO
|
|
break;
|
|
|
|
default:
|
|
if (ent->Flags & IsMandatory)
|
|
{
|
|
// Encountered unknown but mandatory key, bail back to loader.
|
|
g_loaderRetAddr(346 | ((100 + ent->Key) << 9));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
ent++;
|
|
}
|
|
|
|
}
|
|
|
|
Handle envGetMainThreadHandle(void) {
|
|
if (g_mainThreadHandle != INVALID_HANDLE) {
|
|
return g_mainThreadHandle;
|
|
}
|
|
|
|
fatalSimple(MAKERESULT(MODULE_LIBNX, LIBNX_HANDLETOOEARLY));
|
|
}
|
|
|
|
bool envIsNso(void) {
|
|
return g_isNso;
|
|
}
|
|
|
|
bool envHasHeapOverride(void) {
|
|
return g_overrideHeapAddr != NULL;
|
|
}
|
|
|
|
void* envGetHeapOverrideAddr(void) {
|
|
return g_overrideHeapAddr;
|
|
}
|
|
|
|
u64 envGetHeapOverrideSize(void) {
|
|
return g_overrideHeapSize;
|
|
}
|
|
|
|
bool envHasArgv(void) {
|
|
return g_overrideArgv != NULL;
|
|
}
|
|
|
|
u64 envGetArgc(void) {
|
|
return g_overrideArgc;
|
|
}
|
|
|
|
void* envGetArgv(void) {
|
|
return g_overrideArgv;
|
|
}
|
|
|
|
bool envIsSyscallHinted(u8 svc) {
|
|
return !!(g_syscallHints[svc/64] & (1llu << (svc%64)));
|
|
}
|