diff options
| -rw-r--r-- | src/core/hle/service/sm/sm.cpp | 98 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.h | 9 |
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 | ||
| 19 | namespace Service::SM { | 20 | namespace Service::SM { |
| 20 | 21 | ||
| 22 | constexpr ResultCode ERR_NOT_INITIALIZED(ErrorModule::SM, 2); | ||
| 21 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); | 23 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); |
| 22 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); | 24 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); |
| 23 | constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); | 25 | constexpr 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 | ||
| 44 | void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system) { | 42 | Kernel::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 | ||
| 53 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, | 52 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, |
| @@ -114,21 +113,47 @@ void SM::Initialize(Kernel::HLERequestContext& ctx) { | |||
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | void SM::GetService(Kernel::HLERequestContext& ctx) { | 115 | void 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 | |||
| 127 | void 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 | |||
| 134 | static 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); | 145 | ResultVal<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 | ||
| 158 | void SM::RegisterService(Kernel::HLERequestContext& ctx) { | 181 | void 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 | ||
| 188 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { | 207 | void 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 | ||
| 201 | SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) | 217 | SM::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 |
| 35 | class SM final : public ServiceFramework<SM> { | 35 | class SM final : public ServiceFramework<SM> { |
| 36 | public: | 36 | public: |
| 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 | ||
| 40 | private: | 40 | private: |
| 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 | ||
| 51 | class ServiceManager { | 54 | class ServiceManager { |
| 52 | public: | 55 | public: |
| 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(); |