From 94658b9f60d66cd0a47ba4f920c2a9d5a1a173e2 Mon Sep 17 00:00:00 2001 From: plutoo Date: Sat, 13 Jan 2018 00:18:04 +0100 Subject: [PATCH] More loader config --- nx/include/switch/result.h | 33 +++++++++++--------- nx/include/switch/runtime/env.h | 8 +++++ nx/source/runtime/argv.c | 43 ++------------------------ nx/source/runtime/env.c | 55 +++++++++++++++++++++++++++++---- nx/source/services/sm.c | 2 +- 5 files changed, 78 insertions(+), 63 deletions(-) diff --git a/nx/include/switch/result.h b/nx/include/switch/result.h index 0b42e141..4ce799a7 100644 --- a/nx/include/switch/result.h +++ b/nx/include/switch/result.h @@ -19,18 +19,21 @@ ((((module)&0x1FF)) | ((description)&0x1FFF)<<9) #define MODULE_LIBNX 345 -#define LIBNX_BADRELOC 1 -#define LIBNX_OUTOFMEM 2 -#define LIBNX_ALREADYMAPPED 3 -#define LIBNX_BADGETINFO 4 -#define LIBNX_BADQUERYMEMORY 5 -#define LIBNX_ALREADYINITIALIZED 6 -#define LIBNX_NOTINITIALIZED 7 -#define LIBNX_NOTFOUND 8 -#define LIBNX_IOERROR 9 -#define LIBNX_BADINPUT 10 -#define LIBNX_BADREENT 11 -#define LIBNX_BUFFERPRODUCER_ERROR 12 -#define LIBNX_HANDLETOOEARLY 13 -#define LIBNX_HEAPALLOCFAILED 14 -#define LIBNX_PARCEL_ERRBASE 100 +enum { + LIBNX_BADRELOC=1, + LIBNX_OUTOFMEM, + LIBNX_ALREADYMAPPED, + LIBNX_BADGETINFO, + LIBNX_BADQUERYMEMORY, + LIBNX_ALREADYINITIALIZED, + LIBNX_NOTINITIALIZED, + LIBNX_NOTFOUND, + LIBNX_IOERROR, + LIBNX_BADINPUT, + LIBNX_BADREENT, + LIBNX_BUFFERPRODUCER_ERROR, + LIBNX_HANDLETOOEARLY, + LIBNX_HEAPALLOCFAILED, + LIBNX_TOOMANYOVERRIDES, + LIBNX_PARCELERROR, +}; diff --git a/nx/include/switch/runtime/env.h b/nx/include/switch/runtime/env.h index 1cf51116..9a3487e6 100644 --- a/nx/include/switch/runtime/env.h +++ b/nx/include/switch/runtime/env.h @@ -8,3 +8,11 @@ bool envIsNso(void); bool envHasHeapOverride(void); void* envGetHeapOverrideAddr(void); u64 envGetHeapOverrideSize(void); + +bool envHasArgv(void); +u64 envGetArgc(void); +void* envGetArgv(void); + +bool envIsSyscallHinted(u8 svc); + +typedef void __attribute__((noreturn)) (*LoaderReturnFn)(int result_code); diff --git a/nx/source/runtime/argv.c b/nx/source/runtime/argv.c index 2e2801e1..02e00e00 100644 --- a/nx/source/runtime/argv.c +++ b/nx/source/runtime/argv.c @@ -37,6 +37,8 @@ void __system_initArgv(void) rc = svcQueryMemory(&meminfo, &pageinfo, (u64)argdata); + // TODO: Use envHasArgv() here. + // This memory is only mapped when arguments were passed. if (R_FAILED(rc) || meminfo.perm != 0x3) return; @@ -110,46 +112,5 @@ void __system_initArgv(void) } __system_argv[__system_argc] = NULL; - - //TODO: How to handle args for NRO? - - /* - int i; - const char* arglist = envGetSystemArgList(); - const char* temp = arglist; - - // Check if the argument list is present - if (!temp) - return; - - // Retrieve argc - __system_argc = *(u32*)temp; - temp += sizeof(u32); - - // Find the end of the argument data - for (i = 0; i < __system_argc; i ++) - { - for (; *temp; temp ++); - temp ++; - } - - // Reserve heap memory for argv data - u32 argSize = temp - arglist - sizeof(u32); - __system_argv = (char**)fake_heap_start; - fake_heap_start += sizeof(char**)*(__system_argc + 1); - char* argCopy = fake_heap_start; - fake_heap_start += argSize; - - // Fill argv array - memcpy(argCopy, &arglist[4], argSize); - temp = argCopy; - for (i = 0; i < __system_argc; i ++) - { - __system_argv[i] = (char*)temp; - for (; *temp; temp ++); - temp ++; - } - __system_argv[__system_argc] = NULL; - */ } diff --git a/nx/source/runtime/env.c b/nx/source/runtime/env.c index 239e554c..ab4da3d3 100644 --- a/nx/source/runtime/env.c +++ b/nx/source/runtime/env.c @@ -3,9 +3,12 @@ static bool g_isNso = false; static Handle g_mainThreadHandle = INVALID_HANDLE; -static void* g_loaderRetAddr = NULL; +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; @@ -13,6 +16,10 @@ typedef struct { u64 Value[2]; } ConfigEntry; +enum { + IsMandatory = BIT(0), +}; + enum { EntryType_EndOfList=0, EntryType_MainThreadHandle=1, @@ -30,6 +37,10 @@ void envParse(void* ctx, Handle main_thread) { 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; } @@ -53,23 +64,39 @@ void envParse(void* ctx, Handle main_thread) break; case EntryType_OverrideService: - // TODO + smAddOverrideHandle(ent->Value[0], ent->Value[1]); break; case EntryType_Argv: - // TODO + g_overrideArgc = ent->Value[0]; + g_overrideArgv = (void*) ent->Value[1]; break; - case EntryType_SyscallAvailableHint: - // TODO + 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: - // TODO + if (ent->Flags & IsMandatory) + { + // Encountered unknown but mandatory key, bail back to loader. + g_loaderRetAddr(346 | ((100 + ent->Key) << 9)); + } + break; } @@ -101,3 +128,19 @@ void* envGetHeapOverrideAddr(void) { 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))); +} diff --git a/nx/source/services/sm.c b/nx/source/services/sm.c index cce036ea..5966ff5c 100644 --- a/nx/source/services/sm.c +++ b/nx/source/services/sm.c @@ -15,7 +15,7 @@ static size_t g_smOverridesNum = 0; void smAddOverrideHandle(u64 name, Handle handle) { if (g_smOverridesNum == MAX_OVERRIDES) - fatalSimple(1); + fatalSimple(MAKERESULT(MODULE_LIBNX, LIBNX_TOOMANYOVERRIDES)); size_t i = g_smOverridesNum;