NRO loading bringup

This commit is contained in:
plutoo 2018-01-20 00:10:34 +01:00
parent 3a9451bbeb
commit 8ae150d110
5 changed files with 79 additions and 53 deletions

View File

@ -8,13 +8,16 @@ _start:
.org _start+0x80
startup:
// save lr
mov x27, x30
// get aslr base
bl +4
sub x28, x30, #0x84
sub x28, x30, #0x88
// save context ptr and main thread handle
mov x26, x0
mov x27, x1
// context ptr and main thread handle
mov x25, x0
mov x26, x1
// clear .bss
adrp x0, __bss_start__
@ -37,8 +40,9 @@ bss_loop:
bl __nx_dynamic
// initialize system
mov x0, x26
mov x1, x27
mov x0, x25
mov x1, x26
mov x2, x27
bl __libnx_init
// call entrypoint

View File

@ -1,6 +1,33 @@
// Copyright 2018 plutoo
void envParse(void* ctx, Handle main_thread);
typedef struct {
u32 Key;
u32 Flags;
u64 Value[2];
} ConfigEntry;
enum {
EntryFlag_IsMandatory = BIT(0),
};
enum {
EntryType_EndOfList=0,
EntryType_MainThreadHandle=1,
EntryType_NextLoadPath=2,
EntryType_OverrideHeap=3,
EntryType_OverrideService=4,
EntryType_Argv=5,
EntryType_SyscallAvailableHint=6,
EntryType_AppletType=7,
EntryType_AppletWorkaround=8,
EntryType_StdioSockets=9,
EntryType_ProcessHandle=10,
EntryType_LastLoadResult=11
};
typedef void NORETURN (*LoaderReturnFn)(int result_code);
void envParse(void* ctx, Handle main_thread, LoaderReturnFn saved_lr);
Handle envGetMainThreadHandle(void);
bool envIsNso(void);
@ -15,4 +42,4 @@ void* envGetArgv(void);
bool envIsSyscallHinted(u8 svc);
typedef void __attribute__((noreturn)) (*LoaderReturnFn)(int result_code);
LoaderReturnFn envGetExitFuncPtr(void);

View File

@ -47,7 +47,6 @@ Result threadCreate(
rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM);
}
else {
// todo: svcMapMemory returns 0xDC01
void* stack_mirror = virtmemReserveMap(stack_sz);
rc = svcMapMemory(stack_mirror, stack, stack_sz);

View File

@ -8,42 +8,35 @@ 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];
static u64 g_syscallHints[2];
static Handle g_processHandle = INVALID_HANDLE;
typedef struct {
u32 Key;
u32 Flags;
u64 Value[2];
} ConfigEntry;
extern __attribute__((weak)) u32 __nx_applet_type;
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)
void envParse(void* ctx, Handle main_thread, LoaderReturnFn saved_lr)
{
// If we're running under NSO, we should just call svcExitProcess.
// Otherwise we should return to loader via LR.
if (saved_lr == NULL) {
g_loaderRetAddr = (LoaderReturnFn) &svcExitProcess;
}
else {
g_loaderRetAddr = saved_lr;
}
// Detect NSO environment.
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));
g_syscallHints[0] = g_syscallHints[1] = -1ull;
return;
}
// Parse NRO config entries.
ConfigEntry* ent = ctx;
while (ent->Key != EntryType_EndOfList)
@ -54,8 +47,8 @@ void envParse(void* ctx, Handle main_thread)
g_mainThreadHandle = ent->Value[0];
break;
case EntryType_LoaderReturnAddr:
g_loaderRetAddr = (void*) ent->Value[0];
case EntryType_NextLoadPath:
// TODO
break;
case EntryType_OverrideHeap:
@ -72,26 +65,21 @@ void envParse(void* ctx, Handle main_thread)
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);
}
case EntryType_SyscallAvailableHint:
g_syscallHints[0] = ent->Value[0];
g_syscallHints[1] = ent->Value[1];
break;
}
case EntryType_AppletType:
// TODO
__nx_applet_type = ent->Value[0];
break;
case EntryType_ProcessHandle:
g_processHandle = ent->Value[0];
break;
default:
if (ent->Flags & IsMandatory)
if (ent->Flags & EntryFlag_IsMandatory)
{
// Encountered unknown but mandatory key, bail back to loader.
g_loaderRetAddr(MAKERESULT(346, 100 + ent->Key));
@ -142,5 +130,13 @@ void* envGetArgv(void) {
}
bool envIsSyscallHinted(u8 svc) {
return !!(g_syscallHints[svc/64] & (1llu << (svc%64)));
return !!(g_syscallHints[svc/64] & (1ull << (svc%64)));
}
Handle envGetOwnProcessHandle(void) {
return g_processHandle;
}
LoaderReturnFn envGetExitFuncPtr(void) {
return g_loaderRetAddr;
}

View File

@ -97,12 +97,12 @@ void __attribute__((weak)) __appExit(void)
smExit();
}
void __attribute__((weak)) __libnx_init(void* ctx, Handle main_thread)
void __attribute__((weak)) __libnx_init(void* ctx, Handle main_thread, void* saved_lr)
{
// Called by crt0.
// Libnx initialization goes here.
envParse(ctx, main_thread);
envParse(ctx, main_thread, saved_lr);
newlibSetup();
virtmemSetup();
__libnx_initheap();
@ -127,6 +127,6 @@ void __attribute__((weak)) NORETURN __libnx_exit(int rc)
// Clean up services.
__appExit();
svcExitProcess();
envGetExitFuncPtr()(0);
while(1);
}