From f0759b0afc8c813d146768380dd0733adc3dbfcf Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 19 Apr 2018 00:37:01 -0600 Subject: [PATCH] Stratosphere: Add libnx fsp-ldr wrapper to Loader --- stratosphere/loader/source/ldr_main.cpp | 37 +++++- stratosphere/loader/source/lib/fsldr.c | 147 ++++++++++++++++++++++++ stratosphere/loader/source/lib/fsldr.h | 17 +++ 3 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 stratosphere/loader/source/lib/fsldr.c create mode 100644 stratosphere/loader/source/lib/fsldr.h diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 0f4de2522..91d53d57e 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -4,6 +4,8 @@ #include #include +#include +#include "lib/fsldr.h" #include "waitablemanager.hpp" #include "serviceserver.hpp" @@ -19,8 +21,7 @@ u32 __nx_applet_type = AppletType_None; size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; -void __libnx_initheap(void) -{ +void __libnx_initheap(void) { void* addr = nx_inner_heap; size_t size = nx_inner_heap_size; @@ -32,6 +33,38 @@ void __libnx_initheap(void) fake_heap_end = (char*)addr + size; } +void __appInit(void) { + Result rc; + + /* Initialize services we need (TODO: SPL) */ + rc = smInitialize(); + if (R_FAILED(rc)) + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); + + rc = fsInitialize(); + if (R_FAILED(rc)) + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); + + rc = lrInitialize(); + if (R_FAILED(rc)) + fatalSimple(0xCAFE << 4 | 1); + + rc = fsldrInitialize(); + if (R_FAILED(rc)) + fatalSimple(0xCAFE << 4 | 2); + + fsdevInit(); +} + +void __appExit(void) { + /* Cleanup services. */ + fsdevExit(); + fsldrExit(); + lrExit(); + fsExit(); + smExit(); +} + int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); diff --git a/stratosphere/loader/source/lib/fsldr.c b/stratosphere/loader/source/lib/fsldr.c new file mode 100644 index 000000000..18b3ae435 --- /dev/null +++ b/stratosphere/loader/source/lib/fsldr.c @@ -0,0 +1,147 @@ +// Copyright 2018 SciresM +#include +#include +#include +#include +#include +#include +#include +#include +#include "fsldr.h" + +static Service g_fsldrSrv; +static u64 g_fsldrRefCnt; + +Result fsldrSetCurrentProcess(); + +Result fsldrInitialize(void) { + atomicIncrement64(&g_refCnt); + + if (serviceIsActive(&g_fsldrSrv)) + return 0; + + Result rc = smGetService(&g_fsldrSrv, "fsp-ldr"); + + if (R_SUCCEEDED(rc) && kernelAbove400()) { + rc = fsldrSetCurrentProcess(); + } + + return rc; + +} + +void fsldrExit(void) { + if (atomicDecrement64(&g_fsldrRefCnt) == 0) + serviceClose(&g_fsldrSrv); +} + +Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out) { + char send_path[FS_MAX_PATH] = {0}; + IpcCommand c; + ipcInitialize(&c); + ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); + + struct { + u64 magic; + u64 cmd_id; + u64 tid; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + raw->tid = tid; + + strncpy(send_path, path, FS_MAX_PATH); + Result rc = serviceIpcDispatch(&g_fsldrSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreate(&out->s, r.Handles[0]); + } + } + + return rc; +} + +Result fsldrIsArchivedProgram(u64 pid, bool *out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 pid; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1; + raw->pid = pid; + + Result rc = serviceIpcDispatch(&g_fsldrSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u8 is_archived; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *out = is_archived != 0; + } + } + + return rc; +} + +Result fsldrSetCurrentProcess() { + IpcCommand c; + ipcInitialize(&c); + ipcSendPid(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 unk; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 2; + raw->unk = 0; + + rc = serviceIpcDispatch(&g_fsldrSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + diff --git a/stratosphere/loader/source/lib/fsldr.h b/stratosphere/loader/source/lib/fsldr.h new file mode 100644 index 000000000..ab937e4b2 --- /dev/null +++ b/stratosphere/loader/source/lib/fsldr.h @@ -0,0 +1,17 @@ +/** + * @file fsldr.h + * @brief FilesystemProxy-ForLoader (fsp-ldr) service IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include +#include +#include + +Result fsldrInitialize(void); +void fsldrExit(void); + +Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out); +Result fsldrIsArchivedProgram(u64 pid, bool *out); +Result fsldrSetCurrentProcess(); \ No newline at end of file