summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/sm/sm.cpp98
-rw-r--r--src/core/hle/service/sm/sm.h9
2 files changed, 66 insertions, 41 deletions
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 726bef4c3..391db48b1 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -9,6 +9,7 @@
9#include "core/hle/kernel/k_client_port.h" 9#include "core/hle/kernel/k_client_port.h"
10#include "core/hle/kernel/k_client_session.h" 10#include "core/hle/kernel/k_client_session.h"
11#include "core/hle/kernel/k_port.h" 11#include "core/hle/kernel/k_port.h"
12#include "core/hle/kernel/k_scoped_resource_reservation.h"
12#include "core/hle/kernel/k_server_port.h" 13#include "core/hle/kernel/k_server_port.h"
13#include "core/hle/kernel/k_server_session.h" 14#include "core/hle/kernel/k_server_session.h"
14#include "core/hle/kernel/k_session.h" 15#include "core/hle/kernel/k_session.h"
@@ -18,6 +19,7 @@
18 19
19namespace Service::SM { 20namespace Service::SM {
20 21
22constexpr ResultCode ERR_NOT_INITIALIZED(ErrorModule::SM, 2);
21constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); 23constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4);
22constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); 24constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6);
23constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); 25constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7);
@@ -34,20 +36,17 @@ static ResultCode ValidateServiceName(const std::string& name) {
34 LOG_ERROR(Service_SM, "Invalid service name! service={}", name); 36 LOG_ERROR(Service_SM, "Invalid service name! service={}", name);
35 return ERR_INVALID_NAME; 37 return ERR_INVALID_NAME;
36 } 38 }
37 if (name.rfind('\0') != std::string::npos) {
38 LOG_ERROR(Service_SM, "A non null terminated service was passed");
39 return ERR_INVALID_NAME;
40 }
41 return RESULT_SUCCESS; 39 return RESULT_SUCCESS;
42} 40}
43 41
44void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system) { 42Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) {
45 ASSERT(self->sm_interface.expired()); 43 ASSERT(self.sm_interface.expired());
46 44
47 auto sm = std::make_shared<SM>(self, system); 45 auto sm = std::make_shared<SM>(self, system);
48 sm->InstallAsNamedPort(system.Kernel()); 46 self.sm_interface = sm;
49 self->sm_interface = sm; 47 self.controller_interface = std::make_unique<Controller>(system);
50 self->controller_interface = std::make_unique<Controller>(system); 48
49 return sm->CreatePort(system.Kernel());
51} 50}
52 51
53ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, 52ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name,
@@ -114,21 +113,47 @@ void SM::Initialize(Kernel::HLERequestContext& ctx) {
114} 113}
115 114
116void SM::GetService(Kernel::HLERequestContext& ctx) { 115void SM::GetService(Kernel::HLERequestContext& ctx) {
117 IPC::RequestParser rp{ctx}; 116 auto result = GetServiceImpl(ctx);
117 if (result.Succeeded()) {
118 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
119 rb.Push(result.Code());
120 rb.PushMoveObjects(result.Unwrap());
121 } else {
122 IPC::ResponseBuilder rb{ctx, 2};
123 rb.Push(result.Code());
124 }
125}
126
127void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) {
128 auto result = GetServiceImpl(ctx);
129 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
130 rb.Push(result.Code());
131 rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr);
132}
133
134static std::string PopServiceName(IPC::RequestParser& rp) {
118 auto name_buf = rp.PopRaw<std::array<char, 8>>(); 135 auto name_buf = rp.PopRaw<std::array<char, 8>>();
119 auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); 136 std::string result;
137 for (const auto& c : name_buf) {
138 if (c >= ' ' && c <= '~') {
139 result.push_back(c);
140 }
141 }
142 return result;
143}
120 144
121 std::string name(name_buf.begin(), end); 145ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ctx) {
146 if (!is_initialized) {
147 return ERR_NOT_INITIALIZED;
148 }
149
150 IPC::RequestParser rp{ctx};
151 std::string name(PopServiceName(rp));
122 152
123 auto result = service_manager->GetServicePort(name); 153 auto result = service_manager.GetServicePort(name);
124 if (result.Failed()) { 154 if (result.Failed()) {
125 IPC::ResponseBuilder rb{ctx, 2};
126 rb.Push(result.Code());
127 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw); 155 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw);
128 if (name.length() == 0) 156 return result.Code();
129 return; // LibNX Fix
130 UNIMPLEMENTED();
131 return;
132 } 157 }
133 158
134 auto* port = result.Unwrap(); 159 auto* port = result.Unwrap();
@@ -150,18 +175,12 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
150 } 175 }
151 176
152 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); 177 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
153 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; 178 return MakeResult(&session->GetClientSession());
154 rb.Push(RESULT_SUCCESS);
155 rb.PushMoveObjects(session->GetClientSession());
156} 179}
157 180
158void SM::RegisterService(Kernel::HLERequestContext& ctx) { 181void SM::RegisterService(Kernel::HLERequestContext& ctx) {
159 IPC::RequestParser rp{ctx}; 182 IPC::RequestParser rp{ctx};
160 183 std::string name(PopServiceName(rp));
161 const auto name_buf = rp.PopRaw<std::array<char, 8>>();
162 const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
163
164 const std::string name(name_buf.begin(), end);
165 184
166 const auto is_light = static_cast<bool>(rp.PopRaw<u32>()); 185 const auto is_light = static_cast<bool>(rp.PopRaw<u32>());
167 const auto max_session_count = rp.PopRaw<u32>(); 186 const auto max_session_count = rp.PopRaw<u32>();
@@ -169,7 +188,7 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) {
169 LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, 188 LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name,
170 max_session_count, is_light); 189 max_session_count, is_light);
171 190
172 auto handle = service_manager->RegisterService(name, max_session_count); 191 auto handle = service_manager.RegisterService(name, max_session_count);
173 if (handle.Failed()) { 192 if (handle.Failed()) {
174 LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", 193 LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}",
175 handle.Code().raw); 194 handle.Code().raw);
@@ -187,28 +206,31 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) {
187 206
188void SM::UnregisterService(Kernel::HLERequestContext& ctx) { 207void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
189 IPC::RequestParser rp{ctx}; 208 IPC::RequestParser rp{ctx};
209 std::string name(PopServiceName(rp));
190 210
191 const auto name_buf = rp.PopRaw<std::array<char, 8>>();
192 const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
193
194 const std::string name(name_buf.begin(), end);
195 LOG_DEBUG(Service_SM, "called with name={}", name); 211 LOG_DEBUG(Service_SM, "called with name={}", name);
196 212
197 IPC::ResponseBuilder rb{ctx, 2}; 213 IPC::ResponseBuilder rb{ctx, 2};
198 rb.Push(service_manager->UnregisterService(name)); 214 rb.Push(service_manager.UnregisterService(name));
199} 215}
200 216
201SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) 217SM::SM(ServiceManager& service_manager_, Core::System& system_)
202 : ServiceFramework{system_, "sm:", 4}, 218 : ServiceFramework{system_, "sm:", 4},
203 service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { 219 service_manager{service_manager_}, kernel{system_.Kernel()} {
204 static const FunctionInfo functions[] = { 220 RegisterHandlers({
205 {0, &SM::Initialize, "Initialize"}, 221 {0, &SM::Initialize, "Initialize"},
206 {1, &SM::GetService, "GetService"}, 222 {1, &SM::GetService, "GetService"},
207 {2, &SM::RegisterService, "RegisterService"}, 223 {2, &SM::RegisterService, "RegisterService"},
208 {3, &SM::UnregisterService, "UnregisterService"}, 224 {3, &SM::UnregisterService, "UnregisterService"},
209 {4, nullptr, "DetachClient"}, 225 {4, nullptr, "DetachClient"},
210 }; 226 });
211 RegisterHandlers(functions); 227 RegisterHandlersTipc({
228 {0, &SM::Initialize, "Initialize"},
229 {1, &SM::GetServiceTipc, "GetService"},
230 {2, &SM::RegisterService, "RegisterService"},
231 {3, &SM::UnregisterService, "UnregisterService"},
232 {4, nullptr, "DetachClient"},
233 });
212} 234}
213 235
214} // namespace Service::SM 236} // namespace Service::SM
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index fed65af4f..60f0b3f8a 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -34,23 +34,26 @@ class Controller;
34/// Interface to "sm:" service 34/// Interface to "sm:" service
35class SM final : public ServiceFramework<SM> { 35class SM final : public ServiceFramework<SM> {
36public: 36public:
37 explicit SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_); 37 explicit SM(ServiceManager& service_manager_, Core::System& system_);
38 ~SM() override; 38 ~SM() override;
39 39
40private: 40private:
41 void Initialize(Kernel::HLERequestContext& ctx); 41 void Initialize(Kernel::HLERequestContext& ctx);
42 void GetService(Kernel::HLERequestContext& ctx); 42 void GetService(Kernel::HLERequestContext& ctx);
43 void GetServiceTipc(Kernel::HLERequestContext& ctx);
43 void RegisterService(Kernel::HLERequestContext& ctx); 44 void RegisterService(Kernel::HLERequestContext& ctx);
44 void UnregisterService(Kernel::HLERequestContext& ctx); 45 void UnregisterService(Kernel::HLERequestContext& ctx);
45 46
46 std::shared_ptr<ServiceManager> service_manager; 47 ResultVal<Kernel::KClientSession*> GetServiceImpl(Kernel::HLERequestContext& ctx);
48
49 ServiceManager& service_manager;
47 bool is_initialized{}; 50 bool is_initialized{};
48 Kernel::KernelCore& kernel; 51 Kernel::KernelCore& kernel;
49}; 52};
50 53
51class ServiceManager { 54class ServiceManager {
52public: 55public:
53 static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system); 56 static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system);
54 57
55 explicit ServiceManager(Kernel::KernelCore& kernel_); 58 explicit ServiceManager(Kernel::KernelCore& kernel_);
56 ~ServiceManager(); 59 ~ServiceManager();