libnx/nx/source/runtime/env.c
2018-01-13 00:18:04 +01:00

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