From 49af3bcdcba76decc8aec5b6812eac04e488e47f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Wed, 26 Jun 2019 19:05:04 -0400 Subject: [PATCH 1/3] pm: Implement pm:info GetTitleId Searches the process list for a process with the specified ID, returning the title ID if it exists. --- src/core/hle/service/pm/pm.cpp | 49 ++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index ebcc41a43b..b6a7d34740 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -8,6 +8,26 @@ namespace Service::PM { +namespace { + +constexpr ResultCode ERROR_PROCESS_NOT_FOUND{ErrorModule::PM, 1}; + +constexpr u64 NO_PROCESS_FOUND_PID{0}; + +std::optional> SearchProcessList( + const std::vector>& process_list, + std::function&)> predicate) { + const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); + + if (iter == process_list.end()) { + return std::nullopt; + } + + return *iter; +} + +} // Anonymous namespace + class BootMode final : public ServiceFramework { public: explicit BootMode() : ServiceFramework{"pm:bm"} { @@ -60,12 +80,37 @@ public: class Info final : public ServiceFramework { public: - explicit Info() : ServiceFramework{"pm:info"} { + explicit Info(const std::vector>& process_list) + : ServiceFramework{"pm:info"}, process_list(process_list) { static const FunctionInfo functions[] = { - {0, nullptr, "GetTitleId"}, + {0, &Info::GetTitleId, "GetTitleId"}, }; RegisterHandlers(functions); } + +private: + void GetTitleId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); + + const auto process = SearchProcessList(process_list, [process_id](const auto& process) { + return process->GetProcessID() == process_id; + }); + + if (!process.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_PROCESS_NOT_FOUND); + return; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push((*process)->GetTitleID()); + } + + const std::vector>& process_list; }; class Shell final : public ServiceFramework { From 354c254cde34650310c5254c4e7d8672069177c0 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Wed, 26 Jun 2019 19:06:51 -0400 Subject: [PATCH 2/3] pm: Implement pm:dmnt GetTitlePid Takes a title ID and searches for a matching process, returning error if it doesn't exist, otherwise the process ID. --- src/core/hle/service/pm/pm.cpp | 43 ++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index b6a7d34740..d031874101 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -3,6 +3,8 @@ // Refer to the license.txt file included. #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/pm/pm.h" #include "core/hle/service/service.h" @@ -61,12 +63,13 @@ private: class DebugMonitor final : public ServiceFramework { public: - explicit DebugMonitor() : ServiceFramework{"pm:dmnt"} { + explicit DebugMonitor(const Kernel::KernelCore& kernel) + : ServiceFramework{"pm:dmnt"}, kernel(kernel) { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetDebugProcesses"}, {1, nullptr, "StartDebugProcess"}, - {2, nullptr, "GetTitlePid"}, + {2, &DebugMonitor::GetTitlePid, "GetTitlePid"}, {3, nullptr, "EnableDebugForTitleId"}, {4, nullptr, "GetApplicationPid"}, {5, nullptr, "EnableDebugForApplication"}, @@ -76,6 +79,31 @@ public: RegisterHandlers(functions); } + +private: + void GetTitlePid(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto title_id = rp.PopRaw(); + + LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); + + const auto process = + SearchProcessList(kernel.GetProcessList(), [title_id](const auto& process) { + return process->GetTitleID() == title_id; + }); + + if (!process.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_PROCESS_NOT_FOUND); + return; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push((*process)->GetProcessID()); + } + + const Kernel::KernelCore& kernel; }; class Info final : public ServiceFramework { @@ -134,11 +162,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared()->InstallAsService(sm); - std::make_shared()->InstallAsService(sm); - std::make_shared()->InstallAsService(sm); - std::make_shared()->InstallAsService(sm); +void InstallInterfaces(Core::System& system) { + std::make_shared()->InstallAsService(system.ServiceManager()); + std::make_shared(system.Kernel())->InstallAsService(system.ServiceManager()); + std::make_shared(system.Kernel().GetProcessList()) + ->InstallAsService(system.ServiceManager()); + std::make_shared(system.Kernel())->InstallAsService(system.ServiceManager()); } } // namespace Service::PM From bce4bfffb64683c1033a875d35885f4ea650c2a9 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Wed, 26 Jun 2019 19:07:34 -0400 Subject: [PATCH 3/3] pm: Implement pm:shell and pm:dmnt GetApplicationPid Returns the process ID of the current application or 0 if no app is running. --- src/core/hle/service/pm/pm.cpp | 32 +++++++++++++++++++++++++++++--- src/core/hle/service/pm/pm.h | 6 +++--- src/core/hle/service/service.cpp | 2 +- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index d031874101..fe6b5f798f 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -28,6 +28,17 @@ std::optional> SearchProcessList( return *iter; } +void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, + const std::vector>& process_list) { + const auto process = SearchProcessList(process_list, [](const auto& process) { + return process->GetProcessID() == Kernel::Process::ProcessIDMin; + }); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(process.has_value() ? (*process)->GetProcessID() : NO_PROCESS_FOUND_PID); +} + } // Anonymous namespace class BootMode final : public ServiceFramework { @@ -71,7 +82,7 @@ public: {1, nullptr, "StartDebugProcess"}, {2, &DebugMonitor::GetTitlePid, "GetTitlePid"}, {3, nullptr, "EnableDebugForTitleId"}, - {4, nullptr, "GetApplicationPid"}, + {4, &DebugMonitor::GetApplicationPid, "GetApplicationPid"}, {5, nullptr, "EnableDebugForApplication"}, {6, nullptr, "DisableDebug"}, }; @@ -103,6 +114,11 @@ private: rb.Push((*process)->GetProcessID()); } + void GetApplicationPid(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_PM, "called"); + GetApplicationPidGeneric(ctx, kernel.GetProcessList()); + } + const Kernel::KernelCore& kernel; }; @@ -143,7 +159,8 @@ private: class Shell final : public ServiceFramework { public: - explicit Shell() : ServiceFramework{"pm:shell"} { + explicit Shell(const Kernel::KernelCore& kernel) + : ServiceFramework{"pm:shell"}, kernel(kernel) { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "LaunchProcess"}, @@ -152,14 +169,23 @@ public: {3, nullptr, "GetProcessEventWaiter"}, {4, nullptr, "GetProcessEventType"}, {5, nullptr, "NotifyBootFinished"}, - {6, nullptr, "GetApplicationPid"}, + {6, &Shell::GetApplicationPid, "GetApplicationPid"}, {7, nullptr, "BoostSystemMemoryResourceLimit"}, {8, nullptr, "EnableAdditionalSystemThreads"}, + {9, nullptr, "GetUnimplementedEventHandle"}, }; // clang-format on RegisterHandlers(functions); } + +private: + void GetApplicationPid(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_PM, "called"); + GetApplicationPidGeneric(ctx, kernel.GetProcessList()); + } + + const Kernel::KernelCore& kernel; }; void InstallInterfaces(Core::System& system) { diff --git a/src/core/hle/service/pm/pm.h b/src/core/hle/service/pm/pm.h index cc8d3f2152..852e7050c4 100644 --- a/src/core/hle/service/pm/pm.h +++ b/src/core/hle/service/pm/pm.h @@ -4,8 +4,8 @@ #pragma once -namespace Service::SM { -class ServiceManager; +namespace Core { +class System; } namespace Service::PM { @@ -16,6 +16,6 @@ enum class SystemBootMode { }; /// Registers all PM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(Core::System& system); } // namespace Service::PM diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ec9d755b73..0c1af124bd 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -242,7 +242,7 @@ void Init(std::shared_ptr& sm, Core::System& system, PCTL::InstallInterfaces(*sm); PCV::InstallInterfaces(*sm); PlayReport::InstallInterfaces(*sm); - PM::InstallInterfaces(*sm); + PM::InstallInterfaces(system); PSC::InstallInterfaces(*sm); PSM::InstallInterfaces(*sm); Set::InstallInterfaces(*sm);