1 // Copyright 2018 yuzu emulator team
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4
5 #include <algorithm>
6 #include <fmt/format.h>
7 #include "common/assert.h"
8 #include "common/logging/log.h"
9 #include "common/string_util.h"
10 #include "core/core.h"
11 #include "core/hle/ipc.h"
12 #include "core/hle/ipc_helpers.h"
13 #include "core/hle/kernel/client_port.h"
14 #include "core/hle/kernel/kernel.h"
15 #include "core/hle/kernel/process.h"
16 #include "core/hle/kernel/server_port.h"
17 #include "core/hle/kernel/thread.h"
18 #include "core/hle/service/acc/acc.h"
19 #include "core/hle/service/am/am.h"
20 #include "core/hle/service/aoc/aoc_u.h"
21 #include "core/hle/service/apm/apm.h"
22 #include "core/hle/service/audio/audio.h"
23 #include "core/hle/service/bcat/module.h"
24 #include "core/hle/service/bpc/bpc.h"
25 #include "core/hle/service/btdrv/btdrv.h"
26 #include "core/hle/service/btm/btm.h"
27 #include "core/hle/service/caps/caps.h"
28 #include "core/hle/service/erpt/erpt.h"
29 #include "core/hle/service/es/es.h"
30 #include "core/hle/service/eupld/eupld.h"
31 #include "core/hle/service/fatal/fatal.h"
32 #include "core/hle/service/fgm/fgm.h"
33 #include "core/hle/service/filesystem/filesystem.h"
34 #include "core/hle/service/friend/friend.h"
35 #include "core/hle/service/glue/glue.h"
36 #include "core/hle/service/grc/grc.h"
37 #include "core/hle/service/hid/hid.h"
38 #include "core/hle/service/lbl/lbl.h"
39 #include "core/hle/service/ldn/ldn.h"
40 #include "core/hle/service/ldr/ldr.h"
41 #include "core/hle/service/lm/lm.h"
42 #include "core/hle/service/mig/mig.h"
43 #include "core/hle/service/mii/mii.h"
44 #include "core/hle/service/mm/mm_u.h"
45 #include "core/hle/service/ncm/ncm.h"
46 #include "core/hle/service/nfc/nfc.h"
47 #include "core/hle/service/nfp/nfp.h"
48 #include "core/hle/service/nifm/nifm.h"
49 #include "core/hle/service/nim/nim.h"
50 #include "core/hle/service/npns/npns.h"
51 #include "core/hle/service/ns/ns.h"
52 #include "core/hle/service/nvdrv/nvdrv.h"
53 #include "core/hle/service/nvflinger/nvflinger.h"
54 #include "core/hle/service/olsc/olsc.h"
55 #include "core/hle/service/pcie/pcie.h"
56 #include "core/hle/service/pctl/module.h"
57 #include "core/hle/service/pcv/pcv.h"
58 #include "core/hle/service/pm/pm.h"
59 #include "core/hle/service/prepo/prepo.h"
60 #include "core/hle/service/psc/psc.h"
61 #include "core/hle/service/ptm/psm.h"
62 #include "core/hle/service/service.h"
63 #include "core/hle/service/set/settings.h"
64 #include "core/hle/service/sm/sm.h"
65 #include "core/hle/service/sockets/sockets.h"
66 #include "core/hle/service/spl/module.h"
67 #include "core/hle/service/ssl/ssl.h"
68 #include "core/hle/service/time/time.h"
69 #include "core/hle/service/usb/usb.h"
70 #include "core/hle/service/vi/vi.h"
71 #include "core/hle/service/wlan/wlan.h"
72 #include "core/reporter.h"
73
74 namespace Service {
75
76 /**
77 * Creates a function string for logging, complete with the name (or header code, depending
78 * on what's passed in) the port name, and all the cmd_buff arguments.
79 */
MakeFunctionString(std::string_view name,std::string_view port_name,const u32 * cmd_buff)80 [[maybe_unused]] static std::string MakeFunctionString(std::string_view name,
81 std::string_view port_name,
82 const u32* cmd_buff) {
83 // Number of params == bits 0-5 + bits 6-11
84 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
85
86 std::string function_string = fmt::format("function '{}': port={}", name, port_name);
87 for (int i = 1; i <= num_params; ++i) {
88 function_string += fmt::format(", cmd_buff[{}]=0x{:X}", i, cmd_buff[i]);
89 }
90 return function_string;
91 }
92
ServiceFrameworkBase(Core::System & system_,const char * service_name_,u32 max_sessions_,InvokerFn * handler_invoker_)93 ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
94 u32 max_sessions_, InvokerFn* handler_invoker_)
95 : system{system_}, service_name{service_name_}, max_sessions{max_sessions_},
96 handler_invoker{handler_invoker_} {}
97
98 ServiceFrameworkBase::~ServiceFrameworkBase() = default;
99
InstallAsService(SM::ServiceManager & service_manager)100 void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
101 ASSERT(!port_installed);
102
103 auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap();
104 port->SetHleHandler(shared_from_this());
105 port_installed = true;
106 }
107
InstallAsNamedPort(Kernel::KernelCore & kernel)108 void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) {
109 ASSERT(!port_installed);
110
111 auto [server_port, client_port] =
112 Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
113 server_port->SetHleHandler(shared_from_this());
114 kernel.AddNamedPort(service_name, std::move(client_port));
115 port_installed = true;
116 }
117
CreatePort(Kernel::KernelCore & kernel)118 std::shared_ptr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) {
119 ASSERT(!port_installed);
120
121 auto [server_port, client_port] =
122 Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
123 auto port = MakeResult(std::move(server_port)).Unwrap();
124 port->SetHleHandler(shared_from_this());
125 port_installed = true;
126 return client_port;
127 }
128
RegisterHandlersBase(const FunctionInfoBase * functions,std::size_t n)129 void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
130 handlers.reserve(handlers.size() + n);
131 for (std::size_t i = 0; i < n; ++i) {
132 // Usually this array is sorted by id already, so hint to insert at the end
133 handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]);
134 }
135 }
136
ReportUnimplementedFunction(Kernel::HLERequestContext & ctx,const FunctionInfoBase * info)137 void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx,
138 const FunctionInfoBase* info) {
139 auto cmd_buf = ctx.CommandBuffer();
140 std::string function_name = info == nullptr ? fmt::format("{}", ctx.GetCommand()) : info->name;
141
142 fmt::memory_buffer buf;
143 fmt::format_to(buf, "function '{}': port='{}' cmd_buf={{[0]=0x{:X}", function_name,
144 service_name, cmd_buf[0]);
145 for (int i = 1; i <= 8; ++i) {
146 fmt::format_to(buf, ", [{}]=0x{:X}", i, cmd_buf[i]);
147 }
148 buf.push_back('}');
149
150 system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name,
151 service_name);
152 UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf));
153 }
154
InvokeRequest(Kernel::HLERequestContext & ctx)155 void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
156 auto itr = handlers.find(ctx.GetCommand());
157 const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second;
158 if (info == nullptr || info->handler_callback == nullptr) {
159 return ReportUnimplementedFunction(ctx, info);
160 }
161
162 LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
163 handler_invoker(this, info->handler_callback, ctx);
164 }
165
HandleSyncRequest(Kernel::HLERequestContext & context)166 ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) {
167 switch (context.GetCommandType()) {
168 case IPC::CommandType::Close: {
169 IPC::ResponseBuilder rb{context, 2};
170 rb.Push(RESULT_SUCCESS);
171 return IPC::ERR_REMOTE_PROCESS_DEAD;
172 }
173 case IPC::CommandType::ControlWithContext:
174 case IPC::CommandType::Control: {
175 system.ServiceManager().InvokeControlRequest(context);
176 break;
177 }
178 case IPC::CommandType::RequestWithContext:
179 case IPC::CommandType::Request: {
180 InvokeRequest(context);
181 break;
182 }
183 default:
184 UNIMPLEMENTED_MSG("command_type={}", context.GetCommandType());
185 }
186
187 context.WriteToOutgoingCommandBuffer(context.GetThread());
188
189 return RESULT_SUCCESS;
190 }
191
192 /// Initialize Services
Services(std::shared_ptr<SM::ServiceManager> & sm,Core::System & system)193 Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system)
194 : nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system)} {
195
196 // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
197 // here and pass it into the respective InstallInterfaces functions.
198
199 system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
200
201 SM::ServiceManager::InstallInterfaces(sm, system);
202
203 Account::InstallInterfaces(system);
204 AM::InstallInterfaces(*sm, *nv_flinger, system);
205 AOC::InstallInterfaces(*sm, system);
206 APM::InstallInterfaces(system);
207 Audio::InstallInterfaces(*sm, system);
208 BCAT::InstallInterfaces(system);
209 BPC::InstallInterfaces(*sm, system);
210 BtDrv::InstallInterfaces(*sm, system);
211 BTM::InstallInterfaces(*sm, system);
212 Capture::InstallInterfaces(*sm, system);
213 ERPT::InstallInterfaces(*sm, system);
214 ES::InstallInterfaces(*sm, system);
215 EUPLD::InstallInterfaces(*sm, system);
216 Fatal::InstallInterfaces(*sm, system);
217 FGM::InstallInterfaces(*sm, system);
218 FileSystem::InstallInterfaces(system);
219 Friend::InstallInterfaces(*sm, system);
220 Glue::InstallInterfaces(system);
221 GRC::InstallInterfaces(*sm, system);
222 HID::InstallInterfaces(*sm, system);
223 LBL::InstallInterfaces(*sm, system);
224 LDN::InstallInterfaces(*sm, system);
225 LDR::InstallInterfaces(*sm, system);
226 LM::InstallInterfaces(system);
227 Migration::InstallInterfaces(*sm, system);
228 Mii::InstallInterfaces(*sm, system);
229 MM::InstallInterfaces(*sm, system);
230 NCM::InstallInterfaces(*sm, system);
231 NFC::InstallInterfaces(*sm, system);
232 NFP::InstallInterfaces(*sm, system);
233 NIFM::InstallInterfaces(*sm, system);
234 NIM::InstallInterfaces(*sm, system);
235 NPNS::InstallInterfaces(*sm, system);
236 NS::InstallInterfaces(*sm, system);
237 Nvidia::InstallInterfaces(*sm, *nv_flinger, system);
238 OLSC::InstallInterfaces(*sm, system);
239 PCIe::InstallInterfaces(*sm, system);
240 PCTL::InstallInterfaces(*sm, system);
241 PCV::InstallInterfaces(*sm, system);
242 PlayReport::InstallInterfaces(*sm, system);
243 PM::InstallInterfaces(system);
244 PSC::InstallInterfaces(*sm, system);
245 PSM::InstallInterfaces(*sm, system);
246 Set::InstallInterfaces(*sm, system);
247 Sockets::InstallInterfaces(*sm, system);
248 SPL::InstallInterfaces(*sm, system);
249 SSL::InstallInterfaces(*sm, system);
250 Time::InstallInterfaces(system);
251 USB::InstallInterfaces(*sm, system);
252 VI::InstallInterfaces(*sm, system, *nv_flinger);
253 WLAN::InstallInterfaces(*sm, system);
254 }
255
256 Services::~Services() = default;
257
258 } // namespace Service
259