service.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <cstddef>
  5. #include <mutex>
  6. #include <string>
  7. #include <boost/container/flat_map.hpp>
  8. #include "common/common_types.h"
  9. #include "core/hle/kernel/hle_ipc.h"
  10. ////////////////////////////////////////////////////////////////////////////////////////////////////
  11. // Namespace Service
  12. namespace Core {
  13. class System;
  14. }
  15. namespace Kernel {
  16. class HLERequestContext;
  17. class KClientPort;
  18. class KServerSession;
  19. class ServiceThread;
  20. } // namespace Kernel
  21. namespace Service {
  22. namespace FileSystem {
  23. class FileSystemController;
  24. }
  25. namespace NVFlinger {
  26. class HosBinderDriverServer;
  27. class NVFlinger;
  28. } // namespace NVFlinger
  29. namespace SM {
  30. class ServiceManager;
  31. }
  32. /// Default number of maximum connections to a server session.
  33. static constexpr u32 ServerSessionCountMax = 0x40;
  34. static_assert(ServerSessionCountMax == 0x40,
  35. "ServerSessionCountMax isn't 0x40 somehow, this assert is a reminder that this will "
  36. "break lots of things");
  37. /**
  38. * This is an non-templated base of ServiceFramework to reduce code bloat and compilation times, it
  39. * is not meant to be used directly.
  40. *
  41. * @see ServiceFramework
  42. */
  43. class ServiceFrameworkBase : public Kernel::SessionRequestHandler {
  44. public:
  45. /// Returns the string identifier used to connect to the service.
  46. std::string GetServiceName() const {
  47. return service_name;
  48. }
  49. /**
  50. * Returns the maximum number of sessions that can be connected to this service at the same
  51. * time.
  52. */
  53. u32 GetMaxSessions() const {
  54. return max_sessions;
  55. }
  56. /// Creates a port pair and registers this service with the given ServiceManager.
  57. void InstallAsService(SM::ServiceManager& service_manager);
  58. /// Invokes a service request routine using the HIPC protocol.
  59. void InvokeRequest(Kernel::HLERequestContext& ctx);
  60. /// Invokes a service request routine using the HIPC protocol.
  61. void InvokeRequestTipc(Kernel::HLERequestContext& ctx);
  62. /// Creates a port pair and registers it on the kernel's global port registry.
  63. Kernel::KClientPort& CreatePort();
  64. /// Handles a synchronization request for the service.
  65. Result HandleSyncRequest(Kernel::KServerSession& session,
  66. Kernel::HLERequestContext& context) override;
  67. protected:
  68. /// Member-function pointer type of SyncRequest handlers.
  69. template <typename Self>
  70. using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&);
  71. /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
  72. [[nodiscard]] std::scoped_lock<std::mutex> LockService() {
  73. return std::scoped_lock{lock_service};
  74. }
  75. /// System context that the service operates under.
  76. Core::System& system;
  77. /// Identifier string used to connect to the service.
  78. std::string service_name;
  79. private:
  80. template <typename T>
  81. friend class ServiceFramework;
  82. struct FunctionInfoBase {
  83. u32 expected_header;
  84. HandlerFnP<ServiceFrameworkBase> handler_callback;
  85. const char* name;
  86. };
  87. using InvokerFn = void(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member,
  88. Kernel::HLERequestContext& ctx);
  89. explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_,
  90. ServiceThreadType thread_type, u32 max_sessions_,
  91. InvokerFn* handler_invoker_);
  92. ~ServiceFrameworkBase() override;
  93. void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
  94. void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n);
  95. void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info);
  96. /// Maximum number of concurrent sessions that this service can handle.
  97. u32 max_sessions;
  98. /// Flag to store if a port was already create/installed to detect multiple install attempts,
  99. /// which is not supported.
  100. bool service_registered = false;
  101. /// Function used to safely up-cast pointers to the derived class before invoking a handler.
  102. InvokerFn* handler_invoker;
  103. boost::container::flat_map<u32, FunctionInfoBase> handlers;
  104. boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
  105. /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
  106. std::mutex lock_service;
  107. };
  108. /**
  109. * Framework for implementing HLE services. Dispatches on the header id of incoming SyncRequests
  110. * based on a table mapping header ids to handler functions. Service implementations should inherit
  111. * from ServiceFramework using the CRTP (`class Foo : public ServiceFramework<Foo> { ... };`) and
  112. * populate it with handlers by calling #RegisterHandlers.
  113. *
  114. * In order to avoid duplicating code in the binary and exposing too many implementation details in
  115. * the header, this class is split into a non-templated base (ServiceFrameworkBase) and a template
  116. * deriving from it (ServiceFramework). The functions in this class will mostly only erase the type
  117. * of the passed in function pointers and then delegate the actual work to the implementation in the
  118. * base class.
  119. */
  120. template <typename Self>
  121. class ServiceFramework : public ServiceFrameworkBase {
  122. protected:
  123. /// Contains information about a request type which is handled by the service.
  124. struct FunctionInfo : FunctionInfoBase {
  125. // TODO(yuriks): This function could be constexpr, but clang is the only compiler that
  126. // doesn't emit an ICE or a wrong diagnostic because of the static_cast.
  127. /**
  128. * Constructs a FunctionInfo for a function.
  129. *
  130. * @param expected_header_ request header in the command buffer which will trigger dispatch
  131. * to this handler
  132. * @param handler_callback_ member function in this service which will be called to handle
  133. * the request
  134. * @param name_ human-friendly name for the request. Used mostly for logging purposes.
  135. */
  136. FunctionInfo(u32 expected_header_, HandlerFnP<Self> handler_callback_, const char* name_)
  137. : FunctionInfoBase{
  138. expected_header_,
  139. // Type-erase member function pointer by casting it down to the base class.
  140. static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {}
  141. };
  142. /**
  143. * Initializes the handler with no functions installed.
  144. *
  145. * @param system_ The system context to construct this service under.
  146. * @param service_name_ Name of the service.
  147. * @param thread_type Specifies the thread type for this service. If this is set to CreateNew,
  148. * it creates a new thread for it, otherwise this uses the default thread.
  149. * @param max_sessions_ Maximum number of sessions that can be connected to this service at the
  150. * same time.
  151. */
  152. explicit ServiceFramework(Core::System& system_, const char* service_name_,
  153. ServiceThreadType thread_type = ServiceThreadType::Default,
  154. u32 max_sessions_ = ServerSessionCountMax)
  155. : ServiceFrameworkBase(system_, service_name_, thread_type, max_sessions_, Invoker) {}
  156. /// Registers handlers in the service.
  157. template <std::size_t N>
  158. void RegisterHandlers(const FunctionInfo (&functions)[N]) {
  159. RegisterHandlers(functions, N);
  160. }
  161. /**
  162. * Registers handlers in the service. Usually prefer using the other RegisterHandlers
  163. * overload in order to avoid needing to specify the array size.
  164. */
  165. void RegisterHandlers(const FunctionInfo* functions, std::size_t n) {
  166. RegisterHandlersBase(functions, n);
  167. }
  168. /// Registers handlers in the service.
  169. template <std::size_t N>
  170. void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) {
  171. RegisterHandlersTipc(functions, N);
  172. }
  173. /**
  174. * Registers handlers in the service. Usually prefer using the other RegisterHandlers
  175. * overload in order to avoid needing to specify the array size.
  176. */
  177. void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) {
  178. RegisterHandlersBaseTipc(functions, n);
  179. }
  180. private:
  181. /**
  182. * This function is used to allow invocation of pointers to handlers stored in the base class
  183. * without needing to expose the type of this derived class. Pointers-to-member may require a
  184. * fixup when being up or downcast, and thus code that does that needs to know the concrete type
  185. * of the derived class in order to invoke one of it's functions through a pointer.
  186. */
  187. static void Invoker(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member,
  188. Kernel::HLERequestContext& ctx) {
  189. // Cast back up to our original types and call the member function
  190. (static_cast<Self*>(object)->*static_cast<HandlerFnP<Self>>(member))(ctx);
  191. }
  192. };
  193. /**
  194. * The purpose of this class is to own any objects that need to be shared across the other service
  195. * implementations. Will be torn down when the global system instance is shutdown.
  196. */
  197. class Services final {
  198. public:
  199. explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
  200. ~Services();
  201. void KillNVNFlinger();
  202. private:
  203. std::unique_ptr<NVFlinger::HosBinderDriverServer> hos_binder_driver_server;
  204. std::unique_ptr<NVFlinger::NVFlinger> nv_flinger;
  205. };
  206. } // namespace Service