From eb8ee97f1ce3488bf9f3d5867c463a510d04e88d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 10 Apr 2021 15:57:31 -0700 Subject: [PATCH] smm: support tipc/cmif --- nx/include/switch/services/smm.h | 28 ++++++++- nx/source/services/smm.c | 99 ++++++++++++++++++++++++++++---- 2 files changed, 113 insertions(+), 14 deletions(-) diff --git a/nx/include/switch/services/smm.h b/nx/include/switch/services/smm.h index 38980ccc..b591e780 100644 --- a/nx/include/switch/services/smm.h +++ b/nx/include/switch/services/smm.h @@ -7,6 +7,7 @@ #pragma once #include "../types.h" #include "../sf/service.h" +#include "../sf/tipc.h" /// Initialize sm:m. Result smManagerInitialize(void); @@ -14,8 +15,29 @@ Result smManagerInitialize(void); /// Exit sm:m. void smManagerExit(void); -/// Gets the Service object for the actual sm:m service session. -Service* smManagerGetServiceSession(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); + +/// Initialize sm:m exclusively for tipc (requires <12.0.0 and non-Atmosphere). +Result smManagerCmifInitialize(void); + +/// Exit sm:m exclusively for tipc (requires <12.0.0 and non-Atmosphere). +void smManagerCmifExit(void); + +/// Gets the Service object for the actual sm:m service session (requires <12.0.0 and non-Atmosphere). +Service* smManagerCmifGetServiceSession(void); + +Result smManagerCmifRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_size, const void *aci0_sac, size_t aci0_sac_size); +Result smManagerCmifUnregisterProcess(u64 pid); + +/// Initialize sm:m exclusively for tipc (requires 12.0.0+ or Atmosphere). +Result smManagerTipcInitialize(void); + +/// Exit sm:m exclusively for tipc (requires 12.0.0+ or Atmosphere). +void smManagerTipcExit(void); + +/// Gets the TipcService object for the actual sm:m service session (requires 12.0.0+ or Atmosphere). +TipcService* smManagerTipcGetServiceSession(void); + +Result smManagerTipcRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_size, const void *aci0_sac, size_t aci0_sac_size); +Result smManagerTipcUnregisterProcess(u64 pid); diff --git a/nx/source/services/smm.c b/nx/source/services/smm.c index 6f502592..1e2641f1 100644 --- a/nx/source/services/smm.c +++ b/nx/source/services/smm.c @@ -3,24 +3,63 @@ #include "services/smm.h" #include "runtime/hosversion.h" -static Service g_smManagerSrv; +static Service g_smManagerCmifSrv; +static TipcService g_smManagerTipcSrv; -NX_GENERATE_SERVICE_GUARD(smManager); +NX_GENERATE_SERVICE_GUARD(smManagerCmif); +NX_GENERATE_SERVICE_GUARD(smManagerTipc); -Result _smManagerInitialize(void) { - return smGetService(&g_smManagerSrv, "sm:m"); +NX_INLINE bool _smManagerUseTipc(void) { + return hosversionIsAtmosphere() || hosversionAtLeast(12,0,0); } -void _smManagerCleanup(void) { - serviceClose(&g_smManagerSrv); +Result smManagerInitialize(void) { + if (_smManagerUseTipc()) { + return smManagerTipcInitialize(); + } else { + return smManagerCmifInitialize(); + } } -Service* smManagerGetServiceSession(void) { - return &g_smManagerSrv; +void smManagerExit(void) { + if (_smManagerUseTipc()) { + return smManagerTipcExit(); + } else { + return smManagerCmifExit(); + } } Result smManagerRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_size, const void *aci0_sac, size_t aci0_sac_size) { - return serviceDispatchIn(&g_smManagerSrv, 0, pid, + if (_smManagerUseTipc()) { + return smManagerTipcRegisterProcess(pid, acid_sac, acid_sac_size, aci0_sac, aci0_sac_size); + } else { + return smManagerCmifRegisterProcess(pid, acid_sac, acid_sac_size, aci0_sac, aci0_sac_size); + } +} + +Result smManagerUnregisterProcess(u64 pid) { + if (_smManagerUseTipc()) { + return smManagerTipcUnregisterProcess(pid); + } else { + return smManagerCmifUnregisterProcess(pid); + } +} + +Result _smManagerCmifInitialize(void) { + if (_smManagerUseTipc()) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return smGetService(&g_smManagerCmifSrv, "sm:m"); +} + +void _smManagerCmifCleanup(void) { + serviceClose(&g_smManagerCmifSrv); +} + +Service* smManagerCmifGetServiceSession(void) { + return &g_smManagerCmifSrv; +} + +Result smManagerCmifRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_size, const void *aci0_sac, size_t aci0_sac_size) { + return serviceDispatchIn(&g_smManagerCmifSrv, 0, pid, .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias, SfBufferAttr_In | SfBufferAttr_HipcMapAlias, @@ -32,6 +71,44 @@ Result smManagerRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_s ); } -Result smManagerUnregisterProcess(u64 pid) { - return serviceDispatchIn(&g_smManagerSrv, 1, pid); +Result smManagerCmifUnregisterProcess(u64 pid) { + return serviceDispatchIn(&g_smManagerCmifSrv, 1, pid); } + +Result _smManagerTipcInitialize(void) { + if (!_smManagerUseTipc()) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Handle handle; + Result rc = smGetServiceOriginal(&handle, smEncodeName("sm:m")); + + if (R_SUCCEEDED(rc)) { + tipcCreate(&g_smManagerTipcSrv, handle); + } + + return rc; +} + +void _smManagerTipcCleanup(void) { + tipcClose(&g_smManagerTipcSrv); +} + +TipcService* smManagerTipcGetServiceSession(void) { + return &g_smManagerTipcSrv; +} + +Result smManagerTipcRegisterProcess(u64 pid, const void *acid_sac, size_t acid_sac_size, const void *aci0_sac, size_t aci0_sac_size) { + return tipcDispatchIn(&g_smManagerTipcSrv, 0, pid, + .buffer_attrs = { + SfBufferAttr_In | SfBufferAttr_HipcMapAlias, + SfBufferAttr_In | SfBufferAttr_HipcMapAlias, + }, + .buffers = { + { acid_sac, acid_sac_size }, + { aci0_sac, aci0_sac_size }, + }, + ); +} + +Result smManagerTipcUnregisterProcess(u64 pid) { + return tipcDispatchIn(&g_smManagerTipcSrv, 1, pid); +} \ No newline at end of file