diff --git a/nx/include/switch/services/smm.h b/nx/include/switch/services/smm.h new file mode 100644 index 00000000..74beadad --- /dev/null +++ b/nx/include/switch/services/smm.h @@ -0,0 +1,16 @@ +/** + * @file smm.h + * @brief ServiceManager-IManager (sm:m) service IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../services/sm.h" +#include "../services/fs.h" + +Result smManagerInitialize(void); +void smManagerExit(void); + +Result smManagerRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_size, const void *aci0_sac, size_t aci0_sac_size); +Result smManagerUnregisterProcess(u64 pid); diff --git a/nx/source/services/smm.c b/nx/source/services/smm.c new file mode 100644 index 00000000..cd9c4413 --- /dev/null +++ b/nx/source/services/smm.c @@ -0,0 +1,93 @@ +// 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/smm.h" + +static Service g_smManagerSrv; +static u64 g_smManagerRefcnt; + +Result smManagerInitialize(void) { + atomicIncrement64(&g_smManagerRefcnt); + + if (serviceIsActive(&g_smManagerSrv)) + return 0; + + return smGetService(&g_smManagerSrv, "sm:m"); +} + +void smManagerExit(void) { + if (atomicDecrement64(&g_smManagerRefcnt) == 0) + serviceClose(&g_smManagerSrv); +} + +Result smManagerRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_size, const void *aci0_sac, size_t aci0_sac_size) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, acid_sac, acid_sac_size, BufferType_Normal); + ipcAddSendBuffer(&c, aci0_sac, aci0_sac_size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + u64 pid; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + raw->pid = pid; + + Result rc = serviceIpcDispatch(&g_smManagerSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result smManagerUnregisterProcess(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_smManagerSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +}