summaryrefslogtreecommitdiff
path: root/src/core/hle/service/service.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2017-10-14 22:18:42 -0400
committerGravatar bunnei2017-10-14 22:18:42 -0400
commit960a1416de3780e91855d9389c4534acf8c061df (patch)
tree6b373fed639eb39098ba33e6247893919005a2c8 /src/core/hle/service/service.cpp
parentnso: Add a log for loading submodules. (diff)
downloadyuzu-960a1416de3780e91855d9389c4534acf8c061df.tar.gz
yuzu-960a1416de3780e91855d9389c4534acf8c061df.tar.xz
yuzu-960a1416de3780e91855d9389c4534acf8c061df.zip
hle: Initial implementation of NX service framework and IPC.
Diffstat (limited to 'src/core/hle/service/service.cpp')
-rw-r--r--src/core/hle/service/service.cpp115
1 files changed, 43 insertions, 72 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index e1f22ca97..3141b71f5 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -8,17 +8,20 @@
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/string_util.h" 9#include "common/string_util.h"
10#include "core/hle/ipc.h" 10#include "core/hle/ipc.h"
11#include "core/hle/ipc_helpers.h"
11#include "core/hle/kernel/client_port.h" 12#include "core/hle/kernel/client_port.h"
12#include "core/hle/kernel/process.h" 13#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/server_port.h" 14#include "core/hle/kernel/server_port.h"
14#include "core/hle/kernel/server_session.h" 15#include "core/hle/kernel/server_session.h"
16#include "core/hle/kernel/thread.h"
15#include "core/hle/kernel/handle_table.h" 17#include "core/hle/kernel/handle_table.h"
16#include "core/hle/service/dsp_dsp.h" 18#include "core/hle/service/dsp_dsp.h"
17#include "core/hle/service/gsp_gpu.h" 19#include "core/hle/service/gsp_gpu.h"
18#include "core/hle/service/hid/hid.h" 20#include "core/hle/service/hid/hid.h"
21#include "core/hle/service/lm/lm.h"
19#include "core/hle/service/service.h" 22#include "core/hle/service/service.h"
23#include "core/hle/service/sm/controller.h"
20#include "core/hle/service/sm/sm.h" 24#include "core/hle/service/sm/sm.h"
21#include "core/hle/service/sm/srv.h"
22 25
23using Kernel::ClientPort; 26using Kernel::ClientPort;
24using Kernel::ServerPort; 27using Kernel::ServerPort;
@@ -46,42 +49,6 @@ static std::string MakeFunctionString(const char* name, const char* port_name,
46 return function_string; 49 return function_string;
47} 50}
48 51
49Interface::Interface(u32 max_sessions) : max_sessions(max_sessions) {}
50Interface::~Interface() = default;
51
52void Interface::HandleSyncRequest(SharedPtr<ServerSession> server_session) {
53 // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which
54 // session triggered each command.
55
56 u32* cmd_buff = Kernel::GetCommandBuffer();
57 auto itr = m_functions.find(cmd_buff[0]);
58
59 if (itr == m_functions.end() || itr->second.func == nullptr) {
60 std::string function_name = (itr == m_functions.end())
61 ? Common::StringFromFormat("0x%08X", cmd_buff[0])
62 : itr->second.name;
63 LOG_ERROR(
64 Service, "unknown / unimplemented %s",
65 MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
66
67 // TODO(bunnei): Hack - ignore error
68 cmd_buff[1] = 0;
69 return;
70 }
71 LOG_TRACE(Service, "%s",
72 MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
73
74 itr->second.func(this);
75}
76
77void Interface::Register(const FunctionInfo* functions, size_t n) {
78 m_functions.reserve(n);
79 for (size_t i = 0; i < n; ++i) {
80 // Usually this array is sorted by id already, so hint to instead at the end
81 m_functions.emplace_hint(m_functions.cend(), functions[i].id, functions[i]);
82 }
83}
84
85//////////////////////////////////////////////////////////////////////////////////////////////////// 52////////////////////////////////////////////////////////////////////////////////////////////////////
86 53
87ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_sessions, 54ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_sessions,
@@ -113,43 +80,66 @@ void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* function
113 } 80 }
114} 81}
115 82
116void ServiceFrameworkBase::ReportUnimplementedFunction(u32* cmd_buf, const FunctionInfoBase* info) { 83void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info) {
117 IPC::Header header{cmd_buf[0]}; 84 auto cmd_buf = ctx.CommandBuffer();
118 int num_params = header.normal_params_size + header.translate_params_size;
119 std::string function_name = info == nullptr ? fmt::format("{:#08x}", cmd_buf[0]) : info->name; 85 std::string function_name = info == nullptr ? fmt::format("{:#08x}", cmd_buf[0]) : info->name;
120 86
121 fmt::MemoryWriter w; 87 fmt::MemoryWriter w;
122 w.write("function '{}': port='{}' cmd_buf={{[0]={:#x}", function_name, service_name, 88 w.write("function '{}': port='{}' cmd_buf={{[0]={:#x}", function_name, service_name,
123 cmd_buf[0]); 89 cmd_buf[0]);
124 for (int i = 1; i <= num_params; ++i) { 90 for (int i = 1; i <= 8; ++i) {
125 w.write(", [{}]={:#x}", i, cmd_buf[i]); 91 w.write(", [{}]={:#x}", i, cmd_buf[i]);
126 } 92 }
127 w << '}'; 93 w << '}';
128 94
129 LOG_ERROR(Service, "unknown / unimplemented %s", w.c_str()); 95 LOG_ERROR(Service, "unknown / unimplemented %s", w.c_str());
130 // TODO(bunnei): Hack - ignore error 96 // TODO(bunnei): Hack - ignore error
131 cmd_buf[1] = 0; 97 IPC::RequestBuilder rb{ ctx, 1 };
98 rb.Push(RESULT_SUCCESS);
132} 99}
133 100
134void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_session) { 101void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
135 u32* cmd_buf = Kernel::GetCommandBuffer(); 102 auto itr = handlers.find(ctx.GetCommand());
136
137 u32 header_code = cmd_buf[0];
138 auto itr = handlers.find(header_code);
139 const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second; 103 const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second;
140 if (info == nullptr || info->handler_callback == nullptr) { 104 if (info == nullptr || info->handler_callback == nullptr) {
141 return ReportUnimplementedFunction(cmd_buf, info); 105 return ReportUnimplementedFunction(ctx, info);
142 } 106 }
143 107
108 LOG_TRACE(Service, "%s",
109 MakeFunctionString(info->name, GetServiceName().c_str(), ctx.CommandBuffer()).c_str());
110 handler_invoker(this, info->handler_callback, ctx);
111}
112
113void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_session) {
114 u32* cmd_buf = (u32*)Memory::GetPointer(Kernel::GetCurrentThread()->GetTLSAddress());;
115
144 // TODO(yuriks): The kernel should be the one handling this as part of translation after 116 // TODO(yuriks): The kernel should be the one handling this as part of translation after
145 // everything else is migrated 117 // everything else is migrated
146 Kernel::HLERequestContext context(std::move(server_session)); 118 Kernel::HLERequestContext context(std::move(server_session));
147 context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process, 119 context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process,
148 Kernel::g_handle_table); 120 Kernel::g_handle_table);
149 121
150 LOG_TRACE(Service, "%s", 122 switch (context.GetCommandType()) {
151 MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf).c_str()); 123 case IPC::CommandType::Close:
152 handler_invoker(this, info->handler_callback, context); 124 {
125 IPC::RequestBuilder rb{context, 1};
126 rb.Push(RESULT_SUCCESS);
127 break;
128 }
129 case IPC::CommandType::Control:
130 {
131 SM::g_service_manager->InvokeControlRequest(context);
132 break;
133 }
134 case IPC::CommandType::Request:
135 {
136 InvokeRequest(context);
137 break;
138 }
139 default:
140 UNIMPLEMENTED_MSG("command_type=%d", context.GetCommandType());
141 }
142
153 context.WriteToOutgoingCommandBuffer(cmd_buf, *Kernel::g_current_process, 143 context.WriteToOutgoingCommandBuffer(cmd_buf, *Kernel::g_current_process,
154 Kernel::g_handle_table); 144 Kernel::g_handle_table);
155} 145}
@@ -162,33 +152,14 @@ void AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
162 g_kernel_named_ports.emplace(std::move(name), std::move(port)); 152 g_kernel_named_ports.emplace(std::move(name), std::move(port));
163} 153}
164 154
165static void AddNamedPort(Interface* interface_) {
166 SharedPtr<ServerPort> server_port;
167 SharedPtr<ClientPort> client_port;
168 std::tie(server_port, client_port) =
169 ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName());
170
171 server_port->SetHleHandler(std::shared_ptr<Interface>(interface_));
172 AddNamedPort(interface_->GetPortName(), std::move(client_port));
173}
174
175void AddService(Interface* interface_) {
176 auto server_port =
177 SM::g_service_manager
178 ->RegisterService(interface_->GetPortName(), interface_->GetMaxSessions())
179 .Unwrap();
180 server_port->SetHleHandler(std::shared_ptr<Interface>(interface_));
181}
182
183/// Initialize ServiceManager 155/// Initialize ServiceManager
184void Init() { 156void Init() {
185 SM::g_service_manager = std::make_shared<SM::ServiceManager>(); 157 SM::g_service_manager = std::make_shared<SM::ServiceManager>();
186 SM::ServiceManager::InstallInterfaces(SM::g_service_manager); 158 SM::ServiceManager::InstallInterfaces(SM::g_service_manager);
187 159
188 HID::Init(); 160 LM::InstallInterfaces(*SM::g_service_manager);
189 161
190 AddService(new DSP_DSP::Interface); 162 HID::Init();
191 AddService(new GSP::GSP_GPU);
192 163
193 LOG_DEBUG(Service, "initialized OK"); 164 LOG_DEBUG(Service, "initialized OK");
194} 165}