mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 13:02:38 +02:00
NRO loading bringup
This commit is contained in:
parent
3a9451bbeb
commit
8ae150d110
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -3,47 +3,40 @@
|
||||
|
||||
static bool g_isNso = false;
|
||||
static Handle g_mainThreadHandle = INVALID_HANDLE;
|
||||
static LoaderReturnFn 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];
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user