arp.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <memory>
  5. #include "common/logging/log.h"
  6. #include "core/core.h"
  7. #include "core/file_sys/control_metadata.h"
  8. #include "core/hle/ipc_helpers.h"
  9. #include "core/hle/kernel/hle_ipc.h"
  10. #include "core/hle/kernel/k_process.h"
  11. #include "core/hle/kernel/kernel.h"
  12. #include "core/hle/service/glue/arp.h"
  13. #include "core/hle/service/glue/errors.h"
  14. #include "core/hle/service/glue/glue_manager.h"
  15. #include "core/hle/service/service.h"
  16. namespace Service::Glue {
  17. namespace {
  18. std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) {
  19. const auto& list = system.Kernel().GetProcessList();
  20. const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) {
  21. return process->GetProcessID() == process_id;
  22. });
  23. if (iter == list.end()) {
  24. return std::nullopt;
  25. }
  26. return (*iter)->GetTitleID();
  27. }
  28. } // Anonymous namespace
  29. ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_)
  30. : ServiceFramework{system_, "arp:r"}, manager{manager_} {
  31. // clang-format off
  32. static const FunctionInfo functions[] = {
  33. {0, &ARP_R::GetApplicationLaunchProperty, "GetApplicationLaunchProperty"},
  34. {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"},
  35. {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"},
  36. {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"},
  37. {4, nullptr, "GetApplicationInstanceUnregistrationNotifier"},
  38. {5, nullptr, "ListApplicationInstanceId"},
  39. {6, nullptr, "GetMicroApplicationInstanceId"},
  40. {7, nullptr, "GetApplicationCertificate"},
  41. {9998, nullptr, "GetPreomiaApplicationLaunchProperty"},
  42. {9999, nullptr, "GetPreomiaApplicationControlProperty"},
  43. };
  44. // clang-format on
  45. RegisterHandlers(functions);
  46. }
  47. ARP_R::~ARP_R() = default;
  48. void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
  49. IPC::RequestParser rp{ctx};
  50. const auto process_id = rp.PopRaw<u64>();
  51. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  52. const auto title_id = GetTitleIDForProcessID(system, process_id);
  53. if (!title_id.has_value()) {
  54. LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
  55. IPC::ResponseBuilder rb{ctx, 2};
  56. rb.Push(ERR_NOT_REGISTERED);
  57. return;
  58. }
  59. const auto res = manager.GetLaunchProperty(*title_id);
  60. if (res.Failed()) {
  61. LOG_ERROR(Service_ARP, "Failed to get launch property!");
  62. IPC::ResponseBuilder rb{ctx, 2};
  63. rb.Push(res.Code());
  64. return;
  65. }
  66. IPC::ResponseBuilder rb{ctx, 6};
  67. rb.Push(ResultSuccess);
  68. rb.PushRaw(*res);
  69. }
  70. void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx) {
  71. IPC::RequestParser rp{ctx};
  72. const auto title_id = rp.PopRaw<u64>();
  73. LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
  74. const auto res = manager.GetLaunchProperty(title_id);
  75. if (res.Failed()) {
  76. LOG_ERROR(Service_ARP, "Failed to get launch property!");
  77. IPC::ResponseBuilder rb{ctx, 2};
  78. rb.Push(res.Code());
  79. return;
  80. }
  81. IPC::ResponseBuilder rb{ctx, 6};
  82. rb.Push(ResultSuccess);
  83. rb.PushRaw(*res);
  84. }
  85. void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
  86. IPC::RequestParser rp{ctx};
  87. const auto process_id = rp.PopRaw<u64>();
  88. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  89. const auto title_id = GetTitleIDForProcessID(system, process_id);
  90. if (!title_id.has_value()) {
  91. LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
  92. IPC::ResponseBuilder rb{ctx, 2};
  93. rb.Push(ERR_NOT_REGISTERED);
  94. return;
  95. }
  96. const auto res = manager.GetControlProperty(*title_id);
  97. if (res.Failed()) {
  98. LOG_ERROR(Service_ARP, "Failed to get control property!");
  99. IPC::ResponseBuilder rb{ctx, 2};
  100. rb.Push(res.Code());
  101. return;
  102. }
  103. ctx.WriteBuffer(*res);
  104. IPC::ResponseBuilder rb{ctx, 2};
  105. rb.Push(ResultSuccess);
  106. }
  107. void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx) {
  108. IPC::RequestParser rp{ctx};
  109. const auto title_id = rp.PopRaw<u64>();
  110. LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
  111. const auto res = manager.GetControlProperty(title_id);
  112. if (res.Failed()) {
  113. LOG_ERROR(Service_ARP, "Failed to get control property!");
  114. IPC::ResponseBuilder rb{ctx, 2};
  115. rb.Push(res.Code());
  116. return;
  117. }
  118. ctx.WriteBuffer(*res);
  119. IPC::ResponseBuilder rb{ctx, 2};
  120. rb.Push(ResultSuccess);
  121. }
  122. class IRegistrar final : public ServiceFramework<IRegistrar> {
  123. friend class ARP_W;
  124. public:
  125. using IssuerFn = std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)>;
  126. explicit IRegistrar(Core::System& system_, IssuerFn&& issuer)
  127. : ServiceFramework{system_, "IRegistrar"}, issue_process_id{std::move(issuer)} {
  128. // clang-format off
  129. static const FunctionInfo functions[] = {
  130. {0, &IRegistrar::Issue, "Issue"},
  131. {1, &IRegistrar::SetApplicationLaunchProperty, "SetApplicationLaunchProperty"},
  132. {2, &IRegistrar::SetApplicationControlProperty, "SetApplicationControlProperty"},
  133. };
  134. // clang-format on
  135. RegisterHandlers(functions);
  136. }
  137. private:
  138. void Issue(Kernel::HLERequestContext& ctx) {
  139. IPC::RequestParser rp{ctx};
  140. const auto process_id = rp.PopRaw<u64>();
  141. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  142. if (process_id == 0) {
  143. LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
  144. IPC::ResponseBuilder rb{ctx, 2};
  145. rb.Push(ERR_INVALID_PROCESS_ID);
  146. return;
  147. }
  148. if (issued) {
  149. LOG_ERROR(Service_ARP,
  150. "Attempted to issue registrar, but registrar is already issued!");
  151. IPC::ResponseBuilder rb{ctx, 2};
  152. rb.Push(ERR_INVALID_ACCESS);
  153. return;
  154. }
  155. issue_process_id(process_id, launch, std::move(control));
  156. issued = true;
  157. IPC::ResponseBuilder rb{ctx, 2};
  158. rb.Push(ResultSuccess);
  159. }
  160. void SetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
  161. LOG_DEBUG(Service_ARP, "called");
  162. if (issued) {
  163. LOG_ERROR(
  164. Service_ARP,
  165. "Attempted to set application launch property, but registrar is already issued!");
  166. IPC::ResponseBuilder rb{ctx, 2};
  167. rb.Push(ERR_INVALID_ACCESS);
  168. return;
  169. }
  170. IPC::RequestParser rp{ctx};
  171. launch = rp.PopRaw<ApplicationLaunchProperty>();
  172. IPC::ResponseBuilder rb{ctx, 2};
  173. rb.Push(ResultSuccess);
  174. }
  175. void SetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
  176. LOG_DEBUG(Service_ARP, "called");
  177. if (issued) {
  178. LOG_ERROR(
  179. Service_ARP,
  180. "Attempted to set application control property, but registrar is already issued!");
  181. IPC::ResponseBuilder rb{ctx, 2};
  182. rb.Push(ERR_INVALID_ACCESS);
  183. return;
  184. }
  185. control = ctx.ReadBuffer();
  186. IPC::ResponseBuilder rb{ctx, 2};
  187. rb.Push(ResultSuccess);
  188. }
  189. IssuerFn issue_process_id;
  190. bool issued = false;
  191. ApplicationLaunchProperty launch{};
  192. std::vector<u8> control;
  193. };
  194. ARP_W::ARP_W(Core::System& system_, ARPManager& manager_)
  195. : ServiceFramework{system_, "arp:w"}, manager{manager_} {
  196. // clang-format off
  197. static const FunctionInfo functions[] = {
  198. {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
  199. {1, &ARP_W::UnregisterApplicationInstance , "UnregisterApplicationInstance "},
  200. {2, nullptr, "AcquireUpdater"},
  201. };
  202. // clang-format on
  203. RegisterHandlers(functions);
  204. }
  205. ARP_W::~ARP_W() = default;
  206. void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) {
  207. LOG_DEBUG(Service_ARP, "called");
  208. registrar = std::make_shared<IRegistrar>(
  209. system, [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) {
  210. const auto res = GetTitleIDForProcessID(system, process_id);
  211. if (!res.has_value()) {
  212. return ERR_NOT_REGISTERED;
  213. }
  214. return manager.Register(*res, launch, std::move(control));
  215. });
  216. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  217. rb.Push(ResultSuccess);
  218. rb.PushIpcInterface(registrar);
  219. }
  220. void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) {
  221. IPC::RequestParser rp{ctx};
  222. const auto process_id = rp.PopRaw<u64>();
  223. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  224. if (process_id == 0) {
  225. LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
  226. IPC::ResponseBuilder rb{ctx, 2};
  227. rb.Push(ERR_INVALID_PROCESS_ID);
  228. return;
  229. }
  230. const auto title_id = GetTitleIDForProcessID(system, process_id);
  231. if (!title_id.has_value()) {
  232. LOG_ERROR(Service_ARP, "No title ID for process ID!");
  233. IPC::ResponseBuilder rb{ctx, 2};
  234. rb.Push(ERR_NOT_REGISTERED);
  235. return;
  236. }
  237. IPC::ResponseBuilder rb{ctx, 2};
  238. rb.Push(manager.Unregister(*title_id));
  239. }
  240. } // namespace Service::Glue