From 65cca4bf13022611a38e8b35f48f2bb1da66ec36 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 2 May 2018 22:39:22 -0600 Subject: [PATCH] Add support for fsp-pr. --- nx/include/switch.h | 1 + nx/include/switch/services/fspr.h | 18 +++ nx/source/services/fspr.c | 191 ++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 nx/include/switch/services/fspr.h create mode 100644 nx/source/services/fspr.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 886d66cb..a16b72c1 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -35,6 +35,7 @@ extern "C" { #include "switch/services/smm.h" #include "switch/services/fs.h" #include "switch/services/fsldr.h" +#include "switch/services/fspr.h" #include "switch/services/acc.h" #include "switch/services/apm.h" #include "switch/services/applet.h" diff --git a/nx/include/switch/services/fspr.h b/nx/include/switch/services/fspr.h new file mode 100644 index 00000000..7809beec --- /dev/null +++ b/nx/include/switch/services/fspr.h @@ -0,0 +1,18 @@ +/** + * @file fspr.h + * @brief FilesystemProxy-ProgramRegistry (fsp-pr) service IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../services/sm.h" +#include "../services/fs.h" + +Result fsprInitialize(void); +void fsprExit(void); + +Result fsprRegisterProgram(u64 pid, u64 titleID, FsStorageId storageID, const void *fs_access_header, size_t fah_size, const void *fs_access_control, size_t fac_size); +Result fsprUnregisterProgram(u64 pid); +Result fsprSetCurrentProcess(void); +Result fsprSetEnabledProgramVerification(bool enabled); diff --git a/nx/source/services/fspr.c b/nx/source/services/fspr.c new file mode 100644 index 00000000..adbeb1ea --- /dev/null +++ b/nx/source/services/fspr.c @@ -0,0 +1,191 @@ +// Copyright 2018 SciresM +#include +#include "types.h" +#include "result.h" +#include "arm/atomics.h" +#include "kernel/ipc.h" +#include "kernel/detect.h" +#include "services/fs.h" +#include "services/sm.h" +#include "services/fspr.h" + +static Service g_fsprSrv; +static u64 g_fsprRefCnt; + +/* Default access controls -- these will give full filesystem permissions to the requester. */ +static const uint32_t g_fspr_default_fah[] = {0x1, 0xFFFFFFFF, 0xFFFFFFFF, 0x1C, 0, 0x1C, 0}; +static const uint32_t g_fspr_default_fac[] = {0x1, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF}; + +Result fsprInitialize(void) { + atomicIncrement64(&g_fsprRefCnt); + + if (serviceIsActive(&g_fsprSrv)) + return 0; + + Result rc = smGetService(&g_fsprSrv, "fsp-pr"); + + if (R_SUCCEEDED(rc) && kernelAbove400()) { + rc = fsprSetCurrentProcess(); + if (R_FAILED(rc)) { + fsprExit(); + } + } + + return rc; +} + +void fsprExit(void) { + if (atomicDecrement64(&g_fsprRefCnt) == 0) + serviceClose(&g_fsprSrv); +} + +Result fsprRegisterProgram(u64 pid, u64 titleID, FsStorageId storageID, const void *fs_access_header, size_t fah_size, const void *fs_access_control, size_t fac_size) { + IpcCommand c; + ipcInitialize(&c); + + if (fs_access_header == NULL) { + fs_access_header = g_fspr_default_fah; + fah_size = sizeof(g_fspr_default_fah); + } + if (fs_access_control == NULL) { + fs_access_control = g_fspr_default_fac; + fac_size = sizeof(g_fspr_default_fac); + } + + ipcAddSendBuffer(&c, fs_access_header, fah_size, BufferType_Normal); + ipcAddSendBuffer(&c, fs_access_control, fac_size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + u64 sid; + u64 pid; + u64 tid; + u64 fah_size; + u64 fac_size; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + raw->sid = storageID; + raw->pid = pid; + raw->tid = titleID; + raw->fah_size = fah_size; + raw->fac_size = fac_size; + + Result rc = serviceIpcDispatch(&g_fsprSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result fsprUnregisterProgram(u64 pid) { + 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_fsprSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result fsprSetCurrentProcess(void) { + 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; + + Result rc = serviceIpcDispatch(&g_fsprSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + + +Result fsprSetEnabledProgramVerification(bool enabled) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 enabled; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 256; + raw->enabled = enabled ? 1 : 0; + + Result rc = serviceIpcDispatch(&g_fsprSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +}