mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-23 21:32:39 +02:00
NRO loading bringup
This commit is contained in:
parent
3a9451bbeb
commit
8ae150d110
@ -8,13 +8,16 @@ _start:
|
|||||||
|
|
||||||
.org _start+0x80
|
.org _start+0x80
|
||||||
startup:
|
startup:
|
||||||
|
// save lr
|
||||||
|
mov x27, x30
|
||||||
|
|
||||||
// get aslr base
|
// get aslr base
|
||||||
bl +4
|
bl +4
|
||||||
sub x28, x30, #0x84
|
sub x28, x30, #0x88
|
||||||
|
|
||||||
// save context ptr and main thread handle
|
// context ptr and main thread handle
|
||||||
mov x26, x0
|
mov x25, x0
|
||||||
mov x27, x1
|
mov x26, x1
|
||||||
|
|
||||||
// clear .bss
|
// clear .bss
|
||||||
adrp x0, __bss_start__
|
adrp x0, __bss_start__
|
||||||
@ -37,8 +40,9 @@ bss_loop:
|
|||||||
bl __nx_dynamic
|
bl __nx_dynamic
|
||||||
|
|
||||||
// initialize system
|
// initialize system
|
||||||
mov x0, x26
|
mov x0, x25
|
||||||
mov x1, x27
|
mov x1, x26
|
||||||
|
mov x2, x27
|
||||||
bl __libnx_init
|
bl __libnx_init
|
||||||
|
|
||||||
// call entrypoint
|
// call entrypoint
|
||||||
|
@ -1,6 +1,33 @@
|
|||||||
// Copyright 2018 plutoo
|
// 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);
|
Handle envGetMainThreadHandle(void);
|
||||||
bool envIsNso(void);
|
bool envIsNso(void);
|
||||||
@ -15,4 +42,4 @@ void* envGetArgv(void);
|
|||||||
|
|
||||||
bool envIsSyscallHinted(u8 svc);
|
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);
|
rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// todo: svcMapMemory returns 0xDC01
|
|
||||||
void* stack_mirror = virtmemReserveMap(stack_sz);
|
void* stack_mirror = virtmemReserveMap(stack_sz);
|
||||||
rc = svcMapMemory(stack_mirror, stack, stack_sz);
|
rc = svcMapMemory(stack_mirror, stack, stack_sz);
|
||||||
|
|
||||||
|
@ -8,42 +8,35 @@ static void* g_overrideHeapAddr = NULL;
|
|||||||
static u64 g_overrideHeapSize = 0;
|
static u64 g_overrideHeapSize = 0;
|
||||||
static u64 g_overrideArgc = 0;
|
static u64 g_overrideArgc = 0;
|
||||||
static void* g_overrideArgv = NULL;
|
static void* g_overrideArgv = NULL;
|
||||||
static u64 g_syscallHints[0x80/8];
|
static u64 g_syscallHints[2];
|
||||||
|
static Handle g_processHandle = INVALID_HANDLE;
|
||||||
|
|
||||||
typedef struct {
|
extern __attribute__((weak)) u32 __nx_applet_type;
|
||||||
u32 Key;
|
|
||||||
u32 Flags;
|
|
||||||
u64 Value[2];
|
|
||||||
} ConfigEntry;
|
|
||||||
|
|
||||||
enum {
|
void envParse(void* ctx, Handle main_thread, LoaderReturnFn saved_lr)
|
||||||
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 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)
|
if (main_thread != INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
g_mainThreadHandle = main_thread;
|
g_mainThreadHandle = main_thread;
|
||||||
g_isNso = true;
|
g_isNso = true;
|
||||||
|
|
||||||
// For NSO we assume kernelhax thus access to all syscalls.
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse NRO config entries.
|
||||||
ConfigEntry* ent = ctx;
|
ConfigEntry* ent = ctx;
|
||||||
|
|
||||||
while (ent->Key != EntryType_EndOfList)
|
while (ent->Key != EntryType_EndOfList)
|
||||||
@ -54,8 +47,8 @@ void envParse(void* ctx, Handle main_thread)
|
|||||||
g_mainThreadHandle = ent->Value[0];
|
g_mainThreadHandle = ent->Value[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EntryType_LoaderReturnAddr:
|
case EntryType_NextLoadPath:
|
||||||
g_loaderRetAddr = (void*) ent->Value[0];
|
// TODO
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EntryType_OverrideHeap:
|
case EntryType_OverrideHeap:
|
||||||
@ -72,26 +65,21 @@ void envParse(void* ctx, Handle main_thread)
|
|||||||
g_overrideArgv = (void*) ent->Value[1];
|
g_overrideArgv = (void*) ent->Value[1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EntryType_SyscallAvailableHint: {
|
case EntryType_SyscallAvailableHint:
|
||||||
int i, j;
|
g_syscallHints[0] = ent->Value[0];
|
||||||
|
g_syscallHints[1] = ent->Value[1];
|
||||||
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;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case EntryType_AppletType:
|
case EntryType_AppletType:
|
||||||
// TODO
|
__nx_applet_type = ent->Value[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EntryType_ProcessHandle:
|
||||||
|
g_processHandle = ent->Value[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (ent->Flags & IsMandatory)
|
if (ent->Flags & EntryFlag_IsMandatory)
|
||||||
{
|
{
|
||||||
// Encountered unknown but mandatory key, bail back to loader.
|
// Encountered unknown but mandatory key, bail back to loader.
|
||||||
g_loaderRetAddr(MAKERESULT(346, 100 + ent->Key));
|
g_loaderRetAddr(MAKERESULT(346, 100 + ent->Key));
|
||||||
@ -142,5 +130,13 @@ void* envGetArgv(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool envIsSyscallHinted(u8 svc) {
|
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();
|
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.
|
// Called by crt0.
|
||||||
|
|
||||||
// Libnx initialization goes here.
|
// Libnx initialization goes here.
|
||||||
envParse(ctx, main_thread);
|
envParse(ctx, main_thread, saved_lr);
|
||||||
newlibSetup();
|
newlibSetup();
|
||||||
virtmemSetup();
|
virtmemSetup();
|
||||||
__libnx_initheap();
|
__libnx_initheap();
|
||||||
@ -127,6 +127,6 @@ void __attribute__((weak)) NORETURN __libnx_exit(int rc)
|
|||||||
// Clean up services.
|
// Clean up services.
|
||||||
__appExit();
|
__appExit();
|
||||||
|
|
||||||
svcExitProcess();
|
envGetExitFuncPtr()(0);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user