diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index de158eea72..9cf2557063 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -930,8 +930,17 @@ add_library(core STATIC hle/service/pctl/pctl_types.h hle/service/pcv/pcv.cpp hle/service/pcv/pcv.h + hle/service/pm/boot_mode_service.cpp + hle/service/pm/boot_mode_service.h + hle/service/pm/debug_monitor_service.cpp + hle/service/pm/debug_monitor_service.h + hle/service/pm/information_service.cpp + hle/service/pm/information_service.h hle/service/pm/pm.cpp hle/service/pm/pm.h + hle/service/pm/pm_types.h + hle/service/pm/shell_service.cpp + hle/service/pm/shell_service.h hle/service/prepo/prepo.cpp hle/service/prepo/prepo.h hle/service/psc/ovln/ovln_types.h diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp index a32855ffa3..445a1177ea 100644 --- a/src/core/hle/service/am/service/common_state_getter.cpp +++ b/src/core/hle/service/am/service/common_state_getter.cpp @@ -154,9 +154,9 @@ Result ICommonStateGetter::GetPerformanceMode(Out out_perf R_SUCCEED(); } -Result ICommonStateGetter::GetBootMode(Out out_boot_mode) { +Result ICommonStateGetter::GetBootMode(Out out_boot_mode) { LOG_DEBUG(Service_AM, "called"); - *out_boot_mode = Service::PM::SystemBootMode::Normal; + *out_boot_mode = Service::PM::BootMode::Normal; R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/common_state_getter.h b/src/core/hle/service/am/service/common_state_getter.h index 59a46fa94f..3c450d7ff1 100644 --- a/src/core/hle/service/am/service/common_state_getter.h +++ b/src/core/hle/service/am/service/common_state_getter.h @@ -6,7 +6,7 @@ #include "core/hle/service/am/am_types.h" #include "core/hle/service/apm/apm_controller.h" #include "core/hle/service/cmif_types.h" -#include "core/hle/service/pm/pm.h" +#include "core/hle/service/pm/pm_types.h" #include "core/hle/service/service.h" #include "core/hle/service/set/settings_types.h" @@ -37,7 +37,7 @@ private: Result GetDefaultDisplayResolutionChangeEvent(OutCopyHandle out_event); Result GetOperationMode(Out out_operation_mode); Result GetPerformanceMode(Out out_performance_mode); - Result GetBootMode(Out out_boot_mode); + Result GetBootMode(Out out_boot_mode); Result IsVrModeEnabled(Out out_is_vr_mode_enabled); Result SetVrModeEnabled(bool is_vr_mode_enabled); Result SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled); diff --git a/src/core/hle/service/pm/boot_mode_service.cpp b/src/core/hle/service/pm/boot_mode_service.cpp new file mode 100644 index 0000000000..d9b8b4d9a6 --- /dev/null +++ b/src/core/hle/service/pm/boot_mode_service.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/pm/boot_mode_service.h" + +namespace Service::PM { + +BootModeService::BootModeService(Core::System& system_) : ServiceFramework{system_, "pm:bm"} { + static const FunctionInfo functions[] = { + {0, C<&BootModeService::GetBootMode>, "GetBootMode"}, + {1, C<&BootModeService::SetMaintenanceBoot>, "SetMaintenanceBoot"}, + }; + RegisterHandlers(functions); +} + +Result BootModeService::GetBootMode(Out out_boot_mode) { + LOG_DEBUG(Service_PM, "called"); + + *out_boot_mode = static_cast(boot_mode); + + R_SUCCEED(); +} + +Result BootModeService::SetMaintenanceBoot() { + LOG_DEBUG(Service_PM, "called"); + + boot_mode = BootMode::Maintenance; + + R_SUCCEED(); +} + +} // namespace Service::PM diff --git a/src/core/hle/service/pm/boot_mode_service.h b/src/core/hle/service/pm/boot_mode_service.h new file mode 100644 index 0000000000..bac57fea72 --- /dev/null +++ b/src/core/hle/service/pm/boot_mode_service.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/pm/pm_types.h" +#include "core/hle/service/service.h" + +namespace Service::PM { + +class BootModeService final : public ServiceFramework { +public: + explicit BootModeService(Core::System& system_); + +private: + Result GetBootMode(Out out_boot_mode); + Result SetMaintenanceBoot(); + + BootMode boot_mode = BootMode::Normal; +}; + +} // namespace Service::PM diff --git a/src/core/hle/service/pm/debug_monitor_service.cpp b/src/core/hle/service/pm/debug_monitor_service.cpp new file mode 100644 index 0000000000..6cec85927b --- /dev/null +++ b/src/core/hle/service/pm/debug_monitor_service.cpp @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/pm/debug_monitor_service.h" + +namespace Service::PM { + +DebugMonitorService::DebugMonitorService(Core::System& system_) + : ServiceFramework{system_, "pm:dmnt"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetExceptionProcessIdList"}, + {1, nullptr, "StartProcess"}, + {2, C<&DebugMonitorService::GetProcessId>, "GetProcessId"}, + {3, nullptr, "HookToCreateProcess"}, + {4, C<&DebugMonitorService::GetApplicationProcessId>, "GetApplicationProcessId"}, + {5, nullptr, "HookToCreateApplicationProcess"}, + {6, nullptr, "ClearHook"}, + {65000, C<&DebugMonitorService::AtmosphereGetProcessInfo>, "AtmosphereGetProcessInfo"}, + {65001, nullptr, "AtmosphereGetCurrentLimitInfo"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +Result DebugMonitorService::GetProcessId(Out out_process_id, u64 program_id) { + LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); + + auto list = kernel.GetProcessList(); + auto process = + SearchProcessList(list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); + + R_UNLESS(!process.IsNull(), ResultProcessNotFound); + + *out_process_id = ProcessId(process->GetProcessId()); + + R_SUCCEED(); +} + +Result DebugMonitorService::GetApplicationProcessId(Out out_process_id) { + LOG_DEBUG(Service_PM, "called"); + auto list = kernel.GetProcessList(); + R_RETURN(GetApplicationPidGeneric(out_process_id, list)); +} + +Result DebugMonitorService::AtmosphereGetProcessInfo( + OutCopyHandle out_process_handle, Out out_location, + Out out_status, ProcessId process_id) { + // https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/pm/source/impl/pm_process_manager.cpp#L614 + // This implementation is incomplete; only a handle to the process is returned. + const auto pid = process_id.pid; + + LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); + + auto list = kernel.GetProcessList(); + auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); + R_UNLESS(!process.IsNull(), ResultProcessNotFound); + + OverrideStatus override_status{}; + ProgramLocation program_location{ + .program_id = process->GetProgramId(), + .storage_id = 0, + }; + + *out_process_handle = process.GetPointerUnsafe(); + *out_location = program_location; + *out_status = override_status; + + R_SUCCEED(); +} + +} // namespace Service::PM diff --git a/src/core/hle/service/pm/debug_monitor_service.h b/src/core/hle/service/pm/debug_monitor_service.h new file mode 100644 index 0000000000..5c65b7c85b --- /dev/null +++ b/src/core/hle/service/pm/debug_monitor_service.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/pm/pm_types.h" +#include "core/hle/service/service.h" + +namespace Service::PM { + +class DebugMonitorService final : public ServiceFramework { +public: + explicit DebugMonitorService(Core::System& system_); + +private: + Result GetProcessId(Out out_process_id, u64 program_id); + Result GetApplicationProcessId(Out out_process_id); + Result AtmosphereGetProcessInfo(OutCopyHandle out_process_handle, + Out out_location, + Out out_status, ProcessId process_id); +}; +} // namespace Service::PM diff --git a/src/core/hle/service/pm/information_service.cpp b/src/core/hle/service/pm/information_service.cpp new file mode 100644 index 0000000000..f3f2f112cc --- /dev/null +++ b/src/core/hle/service/pm/information_service.cpp @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/pm/information_service.h" +#include "core/hle/service/pm/pm_types.h" + +namespace Service::PM { + +InformationService::InformationService(Core::System& system_) + : ServiceFramework{system_, "pm:info"} { + static const FunctionInfo functions[] = { + {0, C<&InformationService::GetProgramId>, "GetProgramId"}, + {65000, C<&InformationService::AtmosphereGetProcessId>, "AtmosphereGetProcessId"}, + {65001, nullptr, "AtmosphereHasLaunchedProgram"}, + {65002, nullptr, "AtmosphereGetProcessInfo"}, + }; + RegisterHandlers(functions); +} + +Result InformationService::GetProgramId(Out out_program_id, u64 process_id) { + LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); + + auto list = kernel.GetProcessList(); + auto process = + SearchProcessList(list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); + + R_UNLESS(!process.IsNull(), ResultProcessNotFound); + + *out_program_id = process->GetProgramId(); + + R_SUCCEED(); +} + +Result InformationService::AtmosphereGetProcessId(Out out_process_id, u64 program_id) { + LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); + + auto list = system.Kernel().GetProcessList(); + auto process = + SearchProcessList(list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); + + R_UNLESS(!process.IsNull(), ResultProcessNotFound); + + *out_process_id = ProcessId(process->GetProcessId()); + + R_SUCCEED(); +} + +} // namespace Service::PM diff --git a/src/core/hle/service/pm/information_service.h b/src/core/hle/service/pm/information_service.h new file mode 100644 index 0000000000..06e7f785a7 --- /dev/null +++ b/src/core/hle/service/pm/information_service.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::PM { + +class InformationService final : public ServiceFramework { +public: + explicit InformationService(Core::System& system_); + +private: + Result GetProgramId(Out out_program_id, u64 process_id); + Result AtmosphereGetProcessId(Out out_process_id, u64 program_id); +}; + +} // namespace Service::PM diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index b52468e419..e0da6525b7 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -2,264 +2,22 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" -#include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/pm/boot_mode_service.h" +#include "core/hle/service/pm/debug_monitor_service.h" +#include "core/hle/service/pm/information_service.h" #include "core/hle/service/pm/pm.h" +#include "core/hle/service/pm/shell_service.h" #include "core/hle/service/server_manager.h" -#include "core/hle/service/service.h" namespace Service::PM { -namespace { - -constexpr Result ResultProcessNotFound{ErrorModule::PM, 1}; -[[maybe_unused]] constexpr Result ResultAlreadyStarted{ErrorModule::PM, 2}; -[[maybe_unused]] constexpr Result ResultNotTerminated{ErrorModule::PM, 3}; -[[maybe_unused]] constexpr Result ResultDebugHookInUse{ErrorModule::PM, 4}; -[[maybe_unused]] constexpr Result ResultApplicationRunning{ErrorModule::PM, 5}; -[[maybe_unused]] constexpr Result ResultInvalidSize{ErrorModule::PM, 6}; - -constexpr u64 NO_PROCESS_FOUND_PID{0}; - -using ProcessList = std::list>; - -template -Kernel::KScopedAutoObject SearchProcessList(ProcessList& process_list, - F&& predicate) { - const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); - - if (iter == process_list.end()) { - return nullptr; - } - - return iter->GetPointerUnsafe(); -} - -void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { - auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(process.IsNull() ? NO_PROCESS_FOUND_PID : process->GetProcessId()); -} - -} // Anonymous namespace - -class BootMode final : public ServiceFramework { -public: - explicit BootMode(Core::System& system_) : ServiceFramework{system_, "pm:bm"} { - static const FunctionInfo functions[] = { - {0, &BootMode::GetBootMode, "GetBootMode"}, - {1, &BootMode::SetMaintenanceBoot, "SetMaintenanceBoot"}, - }; - RegisterHandlers(functions); - } - -private: - void GetBootMode(HLERequestContext& ctx) { - LOG_DEBUG(Service_PM, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(boot_mode); - } - - void SetMaintenanceBoot(HLERequestContext& ctx) { - LOG_DEBUG(Service_PM, "called"); - - boot_mode = SystemBootMode::Maintenance; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - SystemBootMode boot_mode = SystemBootMode::Normal; -}; - -class DebugMonitor final : public ServiceFramework { -public: - explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetJitDebugProcessIdList"}, - {1, nullptr, "StartProcess"}, - {2, &DebugMonitor::GetProcessId, "GetProcessId"}, - {3, nullptr, "HookToCreateProcess"}, - {4, &DebugMonitor::GetApplicationProcessId, "GetApplicationProcessId"}, - {5, nullptr, "HookToCreateApplicationProgress"}, - {6, nullptr, "ClearHook"}, - {65000, &DebugMonitor::AtmosphereGetProcessInfo, "AtmosphereGetProcessInfo"}, - {65001, nullptr, "AtmosphereGetCurrentLimitInfo"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void GetProcessId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto program_id = rp.PopRaw(); - - LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); - - auto list = kernel.GetProcessList(); - auto process = SearchProcessList( - list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); - - if (process.IsNull()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultProcessNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(process->GetProcessId()); - } - - void GetApplicationProcessId(HLERequestContext& ctx) { - LOG_DEBUG(Service_PM, "called"); - auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); - } - - void AtmosphereGetProcessInfo(HLERequestContext& ctx) { - // https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/pm/source/impl/pm_process_manager.cpp#L614 - // This implementation is incomplete; only a handle to the process is returned. - IPC::RequestParser rp{ctx}; - const auto pid = rp.PopRaw(); - - LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); - - auto list = kernel.GetProcessList(); - auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); - - if (process.IsNull()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultProcessNotFound); - return; - } - - struct ProgramLocation { - u64 program_id; - u8 storage_id; - }; - static_assert(sizeof(ProgramLocation) == 0x10, "ProgramLocation has an invalid size"); - - struct OverrideStatus { - u64 keys_held; - u64 flags; - }; - static_assert(sizeof(OverrideStatus) == 0x10, "OverrideStatus has an invalid size"); - - OverrideStatus override_status{}; - ProgramLocation program_location{ - .program_id = process->GetProgramId(), - .storage_id = 0, - }; - - IPC::ResponseBuilder rb{ctx, 10, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(*process); - rb.PushRaw(program_location); - rb.PushRaw(override_status); - } -}; - -class Info final : public ServiceFramework { -public: - explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} { - static const FunctionInfo functions[] = { - {0, &Info::GetProgramId, "GetProgramId"}, - {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, - {65001, nullptr, "AtmosphereHasLaunchedProgram"}, - {65002, nullptr, "AtmosphereGetProcessInfo"}, - }; - RegisterHandlers(functions); - } - -private: - void GetProgramId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto process_id = rp.PopRaw(); - - LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); - - auto list = kernel.GetProcessList(); - auto process = SearchProcessList( - list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); - - if (process.IsNull()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultProcessNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(process->GetProgramId()); - } - - void AtmosphereGetProcessId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto program_id = rp.PopRaw(); - - LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); - - auto list = system.Kernel().GetProcessList(); - auto process = SearchProcessList( - list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); - - if (process.IsNull()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultProcessNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(process->GetProcessId()); - } -}; - -class Shell final : public ServiceFramework { -public: - explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "LaunchProgram"}, - {1, nullptr, "TerminateProcess"}, - {2, nullptr, "TerminateProgram"}, - {3, nullptr, "GetProcessEventHandle"}, - {4, nullptr, "GetProcessEventInfo"}, - {5, nullptr, "NotifyBootFinished"}, - {6, &Shell::GetApplicationProcessIdForShell, "GetApplicationProcessIdForShell"}, - {7, nullptr, "BoostSystemMemoryResourceLimit"}, - {8, nullptr, "BoostApplicationThreadResourceLimit"}, - {9, nullptr, "GetBootFinishedEventHandle"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void GetApplicationProcessIdForShell(HLERequestContext& ctx) { - LOG_DEBUG(Service_PM, "called"); - auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); - } -}; - void LoopProcess(Core::System& system) { auto server_manager = std::make_unique(system); - server_manager->RegisterNamedService("pm:bm", std::make_shared(system)); - server_manager->RegisterNamedService("pm:dmnt", std::make_shared(system)); - server_manager->RegisterNamedService("pm:info", std::make_shared(system)); - server_manager->RegisterNamedService("pm:shell", std::make_shared(system)); + server_manager->RegisterNamedService("pm:bm", std::make_shared(system)); + server_manager->RegisterNamedService("pm:dmnt", std::make_shared(system)); + server_manager->RegisterNamedService("pm:info", std::make_shared(system)); + server_manager->RegisterNamedService("pm:shell", std::make_shared(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/pm/pm.h b/src/core/hle/service/pm/pm.h index 5d4a1a171c..00f9701b59 100644 --- a/src/core/hle/service/pm/pm.h +++ b/src/core/hle/service/pm/pm.h @@ -9,11 +9,6 @@ class System; namespace Service::PM { -enum class SystemBootMode { - Normal, - Maintenance, -}; - void LoopProcess(Core::System& system); } // namespace Service::PM diff --git a/src/core/hle/service/pm/pm_types.h b/src/core/hle/service/pm/pm_types.h new file mode 100644 index 0000000000..ef0a0d23f6 --- /dev/null +++ b/src/core/hle/service/pm/pm_types.h @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/result.h" +#include "core/hle/service/cmif_types.h" + +namespace Service::PM { + +constexpr Result ResultProcessNotFound{ErrorModule::PM, 1}; +constexpr Result ResultAlreadyStarted{ErrorModule::PM, 2}; +constexpr Result ResultNotTerminated{ErrorModule::PM, 3}; +constexpr Result ResultDebugHookInUse{ErrorModule::PM, 4}; +constexpr Result ResultApplicationRunning{ErrorModule::PM, 5}; +constexpr Result ResultInvalidSize{ErrorModule::PM, 6}; + +constexpr u64 NO_PROCESS_FOUND_PID{0}; + +enum class BootMode { + Normal = 0, + Maintenance = 1, + SafeMode = 2, +}; + +struct ProgramLocation { + u64 program_id; + u8 storage_id; +}; +static_assert(sizeof(ProgramLocation) == 0x10, "ProgramLocation has an invalid size"); + +struct OverrideStatus { + u64 keys_held; + u64 flags; +}; +static_assert(sizeof(OverrideStatus) == 0x10, "OverrideStatus has an invalid size"); + +using ProcessList = std::list>; + +template +static inline Kernel::KScopedAutoObject SearchProcessList( + ProcessList& process_list, F&& predicate) { + const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); + + if (iter == process_list.end()) { + return nullptr; + } + + return iter->GetPointerUnsafe(); +} + +static inline Result GetApplicationPidGeneric(Out out_process_id, + ProcessList& process_list) { + auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); + + *out_process_id = + process.IsNull() ? ProcessId(NO_PROCESS_FOUND_PID) : ProcessId(process->GetProcessId()); + + R_SUCCEED(); +} + +} // namespace Service::PM diff --git a/src/core/hle/service/pm/shell_service.cpp b/src/core/hle/service/pm/shell_service.cpp new file mode 100644 index 0000000000..4e84c14e39 --- /dev/null +++ b/src/core/hle/service/pm/shell_service.cpp @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/pm/pm_types.h" +#include "core/hle/service/pm/shell_service.h" + +namespace Service::PM { + +ShellService::ShellService(Core::System& system_) : ServiceFramework{system_, "pm:shell"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "LaunchProgram"}, + {1, nullptr, "TerminateProcess"}, + {2, nullptr, "TerminateProgram"}, + {3, nullptr, "GetProcessEventHandle"}, + {4, nullptr, "GetProcessEventInfo"}, + {5, nullptr, "NotifyBootFinished"}, + {6, C<&ShellService::GetApplicationProcessIdForShell>, "GetApplicationProcessIdForShell"}, + {7, nullptr, "BoostSystemMemoryResourceLimit"}, + {8, nullptr, "BoostApplicationThreadResourceLimit"}, + {9, nullptr, "GetBootFinishedEventHandle"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +Result ShellService::GetApplicationProcessIdForShell(Out out_process_id) { + LOG_DEBUG(Service_PM, "called"); + + auto list = kernel.GetProcessList(); + + R_RETURN(GetApplicationPidGeneric(out_process_id, list)); +} + +} // namespace Service::PM diff --git a/src/core/hle/service/pm/shell_service.h b/src/core/hle/service/pm/shell_service.h new file mode 100644 index 0000000000..1f7473e89e --- /dev/null +++ b/src/core/hle/service/pm/shell_service.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/service.h" + +namespace Service::PM { + +class ShellService final : public ServiceFramework { +public: + explicit ShellService(Core::System& system_); + +private: + Result GetApplicationProcessIdForShell(Out out_process_id); +}; + +} // namespace Service::PM