libstrat: integrate sm API, add HasService/HasMitm.

This commit is contained in:
Michael Scire 2019-06-24 17:56:00 -07:00
parent bbb689cecf
commit cf5c6cdad9
21 changed files with 784 additions and 330 deletions

View File

@ -16,7 +16,7 @@ include $(DEVKITPRO)/libnx/switch_rules
# INCLUDES is a list of directories containing header files # INCLUDES is a list of directories containing header files
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR)) TARGET := $(notdir $(CURDIR))
SOURCES := source source/spl source/spl/smc source/updater source/patcher source/map source/rnd source/util SOURCES := source source/spl source/spl/smc source/updater source/patcher source/map source/rnd source/util source/sm
DATA := data DATA := data
INCLUDES := include INCLUDES := include

View File

@ -16,7 +16,7 @@
#pragma once #pragma once
#include "mitm/sm_mitm.h" #include "sm.hpp"
#include "ipc.hpp" #include "ipc.hpp"

View File

@ -18,7 +18,6 @@
#include <switch.h> #include <switch.h>
#include "mitm_query_service.hpp" #include "mitm_query_service.hpp"
#include "sm_mitm.h"
#include "mitm_session.hpp" #include "mitm_session.hpp"
#include "../utilities.hpp" #include "../utilities.hpp"
@ -30,29 +29,19 @@ class MitmServer : public IWaitable {
private: private:
Handle port_handle; Handle port_handle;
unsigned int max_sessions; unsigned int max_sessions;
char mitm_name[9]; sts::sm::ServiceName mitm_name;
public: public:
MitmServer(const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s) { MitmServer(const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s), mitm_name(sts::sm::ServiceName::Encode(service_name)) {
Handle query_h = 0; Handle query_h = INVALID_HANDLE;
R_ASSERT(sts::sm::mitm::InstallMitm(&this->port_handle, &query_h, this->mitm_name));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
DoWithSmMitmSession([&]() {
strncpy(mitm_name, service_name, 8);
mitm_name[8] = '\x00';
R_ASSERT(smMitMInstall(&this->port_handle, &query_h, mitm_name));
});
#pragma GCC diagnostic pop
RegisterMitmServerQueryHandle(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared<MitmQueryService<T>>())))); RegisterMitmServerQueryHandle(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared<MitmQueryService<T>>()))));
} }
virtual ~MitmServer() override { virtual ~MitmServer() override {
if (this->port_handle) { if (this->port_handle) {
DoWithSmMitmSession([&]() { R_ASSERT(sts::sm::mitm::UninstallMitm(this->mitm_name));
R_ASSERT(smMitMUninstall(this->mitm_name));
});
svcCloseHandle(port_handle); svcCloseHandle(port_handle);
} }
} }
@ -79,10 +68,7 @@ class MitmServer : public IWaitable {
}); });
u64 client_pid; u64 client_pid;
R_ASSERT(sts::sm::mitm::AcknowledgeSession(forward_service.get(), &client_pid, this->mitm_name));
DoWithSmMitmSession([&]() {
R_ASSERT(smMitMAcknowledgeSession(forward_service.get(), &client_pid, mitm_name));
});
this->GetSessionManager()->AddWaitable(new MitmSession(session_h, client_pid, forward_service, MakeShared(forward_service, client_pid))); this->GetSessionManager()->AddWaitable(new MitmSession(session_h, client_pid, forward_service, MakeShared(forward_service, client_pid)));
return ResultSuccess; return ResultSuccess;

View File

@ -1,25 +0,0 @@
/**
* @file sm_mitm.h
* @brief Service manager (sm) IPC wrapper for Atmosphere extensions.
* @author SciresM
* @copyright libnx Authors
*/
#pragma once
#include <switch.h>
#ifdef __cplusplus
extern "C" {
#endif
Result smMitMInitialize(void);
void smMitMExit(void);
Result smMitMGetService(Service* service_out, const char *name);
Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name);
Result smMitMUninstall(const char *name);
Result smMitMAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name);
Result smMitMIsRegistered(const char *name);
#ifdef __cplusplus
}
#endif

View File

@ -18,5 +18,4 @@
#include "ipc.hpp" #include "ipc.hpp"
#include "services/smm_ams.h"
#include "services/dmntcht.h" #include "services/dmntcht.h"

View File

@ -17,16 +17,6 @@
#pragma once #pragma once
#include <switch.h> #include <switch.h>
#ifdef __cplusplus #include "sm/sm_types.hpp"
extern "C" { #include "sm/sm_api.hpp"
#endif #include "sm/sm_mitm_api.hpp"
Result smManagerAmsInitialize(void);
void smManagerAmsExit(void);
Result smManagerAmsEndInitialDefers(void);
Result smManagerAmsHasMitm(bool *out, const char* name);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "sm_types.hpp"
namespace sts::sm {
/* Ordinary SM API. */
Result GetService(Service *out, ServiceName name);
Result RegisterService(Handle *out, ServiceName name, size_t max_sessions, bool is_light);
Result UnregisterService(ServiceName name);
/* Atmosphere extensions. */
Result HasService(bool *out, ServiceName name);
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "sm_types.hpp"
namespace sts::sm::manager {
/* Manager API. */
Result RegisterProcess(u64 process_id, const void *acid, size_t acid_size, const void *aci, size_t aci_size);
Result UnregisterProcess(u64 process_id);
/* Atmosphere extensions. */
Result EndInitialDefers();
Result HasMitm(bool *out, ServiceName name);
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "sm_types.hpp"
namespace sts::sm::mitm {
/* Mitm API. */
Result InstallMitm(Handle *out_port, Handle *out_query, ServiceName name);
Result UninstallMitm(ServiceName name);
Result AssociateProcessIdAndTitleId(u64 process_id, u64 title_id);
Result AcknowledgeSession(Service *out_service, u64 *out_pid, ServiceName name);
Result HasMitm(bool *out, ServiceName name);
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstring>
namespace sts::sm {
struct ServiceName {
static constexpr size_t MaxLength = 8;
char name[MaxLength];
static constexpr ServiceName Encode(const char *name, size_t name_size) {
ServiceName out{};
for (size_t i = 0; i < MaxLength; i++) {
if (i < name_size) {
out.name[i] = name[i];
} else {
out.name[i] = 0;
}
}
return out;
}
static constexpr ServiceName Encode(const char *name) {
return Encode(name, std::strlen(name));
}
};
static constexpr ServiceName InvalidServiceName = ServiceName::Encode("");
static_assert(alignof(ServiceName) == 1, "ServiceName definition!");
inline bool operator==(const ServiceName &lhs, const ServiceName &rhs) {
return std::memcmp(&lhs, &rhs, sizeof(ServiceName)) == 0;
}
inline bool operator!=(const ServiceName &lhs, const ServiceName &rhs) {
return !(lhs == rhs);
}
/* For Debug Monitor extensions. */
struct ServiceRecord {
ServiceName service;
u64 owner_pid;
u64 max_sessions;
u64 mitm_pid;
u64 mitm_waiting_ack_pid;
bool is_light;
bool mitm_waiting_ack;
};
static_assert(sizeof(ServiceRecord) == 0x30, "ServiceRecord definition!");
/* For process validation. */
static constexpr u64 InvalidProcessId = static_cast<u64>(-1ull);
}

View File

@ -19,7 +19,6 @@
#include <cstdlib> #include <cstdlib>
#include "hossynch.hpp" #include "hossynch.hpp"
#include "mitm/sm_mitm.h"
static inline uintptr_t GetIoMapping(const u64 io_addr, const u64 io_size) { static inline uintptr_t GetIoMapping(const u64 io_addr, const u64 io_size) {
u64 vaddr; u64 vaddr;
@ -117,7 +116,6 @@ static inline bool ShouldBlankProdInfo() {
} }
HosRecursiveMutex &GetSmSessionMutex(); HosRecursiveMutex &GetSmSessionMutex();
HosRecursiveMutex &GetSmMitmSessionMutex();
template<typename F> template<typename F>
static void DoWithSmSession(F f) { static void DoWithSmSession(F f) {
@ -128,13 +126,3 @@ static void DoWithSmSession(F f) {
smExit(); smExit();
} }
} }
template<typename F>
static void DoWithSmMitmSession(F f) {
std::scoped_lock<HosRecursiveMutex &> lk(GetSmMitmSessionMutex());
{
R_ASSERT(smMitMInitialize());
f();
smMitMExit();
}
}

309
source/sm/sm_ams.c Normal file
View File

@ -0,0 +1,309 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <switch.h>
#include <switch/arm/atomics.h>
#include "sm_ams.h"
static Service g_smMitmSrv;
static u64 g_mitmRefCnt;
Result smAtmosphereHasService(bool *out, const char *name) {
IpcCommand c;
ipcInitialize(&c);
Service *srv = smGetServiceSession();
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65100;
raw->service_name = smEncodeName(name);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u8 has_service;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out = resp->has_service != 0;
}
}
return rc;
}
Result smAtmosphereHasMitm(bool *out, const char *name) {
IpcCommand c;
ipcInitialize(&c);
Service *srv = smGetServiceSession();
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65004;
raw->service_name = smEncodeName(name);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u8 has_mitm;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out = resp->has_mitm != 0;
}
}
return rc;
}
Result smAtmosphereMitmInitialize(void) {
atomicIncrement64(&g_mitmRefCnt);
if (serviceIsActive(&g_smMitmSrv))
return 0;
Handle sm_handle;
Result rc = svcConnectToNamedPort(&sm_handle, "sm:");
while (R_VALUE(rc) == KERNELRESULT(NotFound)) {
svcSleepThread(50000000ul);
rc = svcConnectToNamedPort(&sm_handle, "sm:");
}
if (R_SUCCEEDED(rc)) {
serviceCreate(&g_smMitmSrv, sm_handle);
}
if (R_SUCCEEDED(rc)) {
IpcCommand c;
ipcInitialize(&c);
ipcSendPid(&c);
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u64 reserved[2];
} *raw;
raw = serviceIpcPrepareHeader(&g_smMitmSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->zero = 0;
rc = serviceIpcDispatch(&g_smMitmSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_smMitmSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
}
if (R_FAILED(rc))
smAtmosphereMitmExit();
return rc;
}
void smAtmosphereMitmExit(void) {
if (atomicDecrement64(&g_mitmRefCnt) == 0) {
serviceClose(&g_smMitmSrv);
}
}
Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, const char *name) {
IpcCommand c;
ipcInitialize(&c);
Service *srv = &g_smMitmSrv;
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65000;
raw->service_name = smEncodeName(name);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*handle_out = r.Handles[0];
*query_out = r.Handles[1];
}
}
return rc;
}
Result smAtmosphereMitmUninstall(const char *name) {
IpcCommand c;
ipcInitialize(&c);
Service *srv = &g_smMitmSrv;
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65001;
raw->service_name = smEncodeName(name);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result smAtmosphereMitmAssociateProcessIdAndTitleId(u64 pid, u64 tid) {
IpcCommand c;
ipcInitialize(&c);
Service *srv = &g_smMitmSrv;
struct {
u64 magic;
u64 cmd_id;
u64 pid;
u64 tid;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65002;
raw->pid = pid;
raw->tid = tid;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name) {
IpcCommand c;
ipcInitialize(&c);
Service *srv = &g_smMitmSrv;
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65003;
raw->service_name = smEncodeName(name);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u64 pid;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*pid_out = resp->pid;
serviceCreate(srv_out, r.Handles[0]);
}
}
return rc;
}

27
source/sm/sm_ams.h Normal file
View File

@ -0,0 +1,27 @@
/**
* @file sm_ams.h
* @brief Service manager (sm) IPC wrapper for Atmosphere extensions.
* @author SciresM
* @copyright libnx Authors
*/
#pragma once
#include <switch.h>
#ifdef __cplusplus
extern "C" {
#endif
Result smAtmosphereHasService(bool *out, const char *name);
Result smAtmosphereHasMitm(bool *out, const char *name);
Result smAtmosphereMitmInitialize(void);
void smAtmosphereMitmExit(void);
Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, const char *name);
Result smAtmosphereMitmUninstall(const char *name);
Result smAtmosphereMitmAssociateProcessIdAndTitleId(u64 pid, u64 tid);
Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name);
#ifdef __cplusplus
}
#endif

52
source/sm/sm_api.cpp Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <switch.h>
#include <stratosphere.hpp>
#include <stratosphere/sm.hpp>
#include "sm_ams.h"
#include "sm_utils.hpp"
namespace sts::sm {
/* Ordinary SM API. */
Result GetService(Service *out, ServiceName name) {
return impl::DoWithUserSession([&]() {
return smGetService(out, name.name);
});
}
Result RegisterService(Handle *out, ServiceName name, size_t max_sessions, bool is_light) {
return impl::DoWithUserSession([&]() {
return smRegisterService(out, name.name, is_light, static_cast<int>(max_sessions));
});
}
Result UnregisterService(ServiceName name) {
return impl::DoWithUserSession([&]() {
return smUnregisterService(name.name);
});
}
/* Atmosphere extensions. */
Result HasService(bool *out, ServiceName name) {
return impl::DoWithUserSession([&]() {
return smAtmosphereHasService(out, name.name);
});
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <switch.h>
#include <stratosphere.hpp>
#include <stratosphere/sm.hpp>
#include <stratosphere/sm/sm_manager_api.hpp>
#include "smm_ams.h"
namespace sts::sm::manager {
/* Manager API. */
Result RegisterProcess(u64 process_id, const void *acid, size_t acid_size, const void *aci, size_t aci_size) {
return smManagerRegisterProcess(process_id, acid, acid_size, aci, aci_size);
}
Result UnregisterProcess(u64 process_id) {
return smManagerUnregisterProcess(process_id);
}
/* Atmosphere extensions. */
Result EndInitialDefers() {
return smManagerAtmosphereEndInitialDefers();
}
Result HasMitm(bool *out, ServiceName name) {
return smManagerAtmosphereHasMitm(out, name.name);
}
}

57
source/sm/sm_mitm_api.cpp Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <switch.h>
#include <stratosphere.hpp>
#include <stratosphere/sm.hpp>
#include "sm_ams.h"
#include "sm_utils.hpp"
namespace sts::sm::mitm {
/* Mitm API. */
Result InstallMitm(Handle *out_port, Handle *out_query, ServiceName name) {
return impl::DoWithMitmSession([&]() {
return smAtmosphereMitmInstall(out_port, out_query, name.name);
});
}
Result UninstallMitm(ServiceName name) {
return impl::DoWithMitmSession([&]() {
return smAtmosphereMitmUninstall(name.name);
});
}
Result AssociateProcessIdAndTitleId(u64 process_id, u64 title_id) {
return impl::DoWithMitmSession([&]() {
return smAtmosphereMitmAssociateProcessIdAndTitleId(process_id, title_id);
});
}
Result AcknowledgeSession(Service *out_service, u64 *out_pid, ServiceName name) {
return impl::DoWithMitmSession([&]() {
return smAtmosphereMitmAcknowledgeSession(out_service, out_pid, name.name);
});
}
Result HasMitm(bool *out, ServiceName name) {
return impl::DoWithUserSession([&]() {
return smAtmosphereHasMitm(out, name.name);
});
}
}

38
source/sm/sm_utils.cpp Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sm_utils.hpp"
namespace sts::sm::impl {
namespace {
/* Globals. */
HosRecursiveMutex g_user_session_mutex;
HosRecursiveMutex g_mitm_session_mutex;
}
/* Utilities. */
HosRecursiveMutex &GetUserSessionMutex() {
return g_user_session_mutex;
}
HosRecursiveMutex &GetMitmSessionMutex() {
return g_mitm_session_mutex;
}
}

53
source/sm/sm_utils.hpp Normal file
View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
#include <stratosphere/sm.hpp>
#include "sm_ams.h"
namespace sts::sm::impl {
/* Utilities. */
HosRecursiveMutex &GetUserSessionMutex();
HosRecursiveMutex &GetMitmSessionMutex();
template<typename F>
Result DoWithUserSession(F f) {
std::scoped_lock<HosRecursiveMutex &> lk(GetUserSessionMutex());
{
R_ASSERT(smInitialize());
ON_SCOPE_EXIT { smExit(); };
return f();
}
}
template<typename F>
Result DoWithMitmSession(F f) {
std::scoped_lock<HosRecursiveMutex &> lk(GetMitmSessionMutex());
{
R_ASSERT(smAtmosphereMitmInitialize());
ON_SCOPE_EXIT { smAtmosphereMitmExit(); };
return f();
}
}
}

View File

@ -15,41 +15,24 @@
*/ */
#include <switch.h> #include <switch.h>
#include <switch/arm/atomics.h> #include "smm_ams.h"
#include <stratosphere/services/smm_ams.h>
static Service g_smManagerAmsSrv; Result smManagerAtmosphereEndInitialDefers(void) {
static u64 g_smManagerAmsRefcnt;
Result smManagerAmsInitialize(void) {
atomicIncrement64(&g_smManagerAmsRefcnt);
if (serviceIsActive(&g_smManagerAmsSrv))
return 0;
return smGetService(&g_smManagerAmsSrv, "sm:m");
}
void smManagerAmsExit(void) {
if (atomicDecrement64(&g_smManagerAmsRefcnt) == 0)
serviceClose(&g_smManagerAmsSrv);
}
Result smManagerAmsEndInitialDefers(void) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
Service *srv = smManagerGetServiceSession();
struct { struct {
u64 magic; u64 magic;
u64 cmd_id; u64 cmd_id;
} *raw; } *raw;
raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 65000; raw->cmd_id = 65000;
Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
@ -58,7 +41,7 @@ Result smManagerAmsEndInitialDefers(void) {
u64 result; u64 result;
} *resp; } *resp;
serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw; resp = r.Raw;
rc = resp->result; rc = resp->result;
@ -68,9 +51,10 @@ Result smManagerAmsEndInitialDefers(void) {
} }
Result smManagerAmsHasMitm(bool *out, const char* name) { Result smManagerAtmosphereHasMitm(bool *out, const char* name) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
Service *srv = smManagerGetServiceSession();
struct { struct {
u64 magic; u64 magic;
@ -78,12 +62,12 @@ Result smManagerAmsHasMitm(bool *out, const char* name) {
u64 service_name; u64 service_name;
} *raw; } *raw;
raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 65001; raw->cmd_id = 65001;
raw->service_name = smEncodeName(name); raw->service_name = smEncodeName(name);
Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
@ -93,7 +77,7 @@ Result smManagerAmsHasMitm(bool *out, const char* name) {
u8 has_mitm; u8 has_mitm;
} *resp; } *resp;
serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw; resp = r.Raw;
rc = resp->result; rc = resp->result;

19
source/sm/smm_ams.h Normal file
View File

@ -0,0 +1,19 @@
/**
* @file smm_ams.h
* @brief Service manager manager (sm:m) IPC wrapper for Atmosphere extensions.
* @author SciresM
* @copyright libnx Authors
*/
#pragma once
#include <switch.h>
#ifdef __cplusplus
extern "C" {
#endif
Result smManagerAtmosphereEndInitialDefers(void);
Result smManagerAtmosphereHasMitm(bool *out, const char* name);
#ifdef __cplusplus
}
#endif

View File

@ -1,230 +0,0 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <switch.h>
#include <switch/arm/atomics.h>
#include <stratosphere/mitm/sm_mitm.h>
static Handle g_smMitmHandle = INVALID_HANDLE;
static u64 g_refCnt;
Result smMitMInitialize(void) {
atomicIncrement64(&g_refCnt);
if (g_smMitmHandle != INVALID_HANDLE)
return 0;
Result rc = svcConnectToNamedPort(&g_smMitmHandle, "sm:");
if (R_SUCCEEDED(rc)) {
IpcCommand c;
ipcInitialize(&c);
ipcSendPid(&c);
struct {
u64 magic;
u64 cmd_id;
u64 zero;
u64 reserved[2];
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->zero = 0;
rc = ipcDispatch(g_smMitmHandle);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
}
if (R_FAILED(rc))
smExit();
return rc;
}
void smMitMExit(void) {
if (atomicDecrement64(&g_refCnt) == 0) {
svcCloseHandle(g_smMitmHandle);
g_smMitmHandle = INVALID_HANDLE;
}
}
Result smMitMGetService(Service* service_out, const char *name_str)
{
u64 name = smEncodeName(name_str);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
u64 reserved[2];
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
raw->service_name = name;
Result rc = ipcDispatch(g_smMitmHandle);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
service_out->type = ServiceType_Normal;
service_out->handle = r.Handles[0];
}
}
return rc;
}
Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65000;
raw->service_name = smEncodeName(name);
Result rc = ipcDispatch(g_smMitmHandle);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*handle_out = r.Handles[0];
*query_out = r.Handles[1];
}
}
return rc;
}
Result smMitMUninstall(const char *name) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
u64 reserved;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65001;
raw->service_name = smEncodeName(name);
Result rc = ipcDispatch(g_smMitmHandle);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result smMitMAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 service_name;
u64 reserved;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 65003;
raw->service_name = smEncodeName(name);
Result rc = ipcDispatch(g_smMitmHandle);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u64 pid;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*pid_out = resp->pid;
serviceCreate(srv_out, r.Handles[0]);
}
}
return rc;
}