From 960a1416de3780e91855d9389c4534acf8c061df Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 14 Oct 2017 22:18:42 -0400 Subject: hle: Initial implementation of NX service framework and IPC. --- src/core/hle/service/sm/sm.cpp | 91 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service/sm/sm.cpp') diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 854ab9a05..2068471f2 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -4,16 +4,21 @@ #include #include "common/assert.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" #include "core/hle/kernel/server_port.h" #include "core/hle/result.h" +#include "core/hle/service/sm/controller.h" #include "core/hle/service/sm/sm.h" -#include "core/hle/service/sm/srv.h" namespace Service { namespace SM { +void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) { + controller_interface->InvokeRequest(context); +} + static ResultCode ValidateServiceName(const std::string& name) { if (name.size() <= 0 || name.size() > 8) { return ERR_INVALID_NAME_SIZE; @@ -25,11 +30,12 @@ static ResultCode ValidateServiceName(const std::string& name) { } void ServiceManager::InstallInterfaces(std::shared_ptr self) { - ASSERT(self->srv_interface.expired()); + ASSERT(self->sm_interface.expired()); - auto srv = std::make_shared(self); - srv->InstallAsNamedPort(); - self->srv_interface = srv; + auto sm = std::make_shared(self); + sm->InstallAsNamedPort(); + self->sm_interface = sm; + self->controller_interface = std::make_unique(); } ResultVal> ServiceManager::RegisterService( @@ -69,5 +75,80 @@ ResultVal> ServiceManager::ConnectToSer std::shared_ptr g_service_manager; +/** + * SM::Initialize service function + * Inputs: + * 0: 0x00000000 + * Outputs: + * 1: ResultCode + */ +void SM::Initialize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 1}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_SM, "called"); +} + +/** + * SM::GetServiceHandle service function + * Inputs: + * 0: 0x00000001 + * 1: Unknown + * 2: Unknown + * 3-4: 8-byte UTF-8 service name + * Outputs: + * 1: ResultCode + * 3: Service handle + */ +void SM::GetService(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u32 unk1 = rp.Pop(); + u32 unk2 = rp.Pop(); + auto name_buf = rp.PopRaw>(); + std::string name(name_buf.data()); + + // TODO(yuriks): Permission checks go here + + auto client_port = service_manager->GetServicePort(name); + if (client_port.Failed()) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0, 0); + rb.Push(client_port.Code()); + LOG_ERROR(Service_SM, "called service=%s -> error 0x%08X", name.c_str(), + client_port.Code().raw); + return; + } + + auto session = client_port.Unwrap()->Connect(); + if (session.Succeeded()) { + LOG_DEBUG(Service_SM, "called service=%s -> session=%u", name.c_str(), + (*session)->GetObjectId()); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0, 1); + rb.Push(session.Code()); + rb.PushObjects(std::move(session).Unwrap()); + } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED /*&& return_port_on_failure*/) { + LOG_WARNING(Service_SM, "called service=%s -> ERR_MAX_CONNECTIONS_REACHED, *port*=%u", + name.c_str(), (*client_port)->GetObjectId()); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0, 1); + rb.Push(ERR_MAX_CONNECTIONS_REACHED); + rb.PushObjects(std::move(client_port).Unwrap()); + } else { + LOG_ERROR(Service_SM, "called service=%s -> error 0x%08X", name.c_str(), session.Code()); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0, 0); + rb.Push(session.Code()); + } +} + +SM::SM(std::shared_ptr service_manager) + : ServiceFramework("sm:", 4), service_manager(std::move(service_manager)) { + static const FunctionInfo functions[] = { + {0x00000000, &SM::Initialize, "Initialize"}, + {0x00000001, &SM::GetService, "GetService"}, + {0x00000002, nullptr, "RegisterService"}, + {0x00000003, nullptr, "UnregisterService"}, + }; + RegisterHandlers(functions); +} + +SM::~SM() = default; + } // namespace SM } // namespace Service -- cgit v1.2.3