diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 805f94650..f07c6f236 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -231,6 +231,9 @@ namespace ams::kern { return this->cond_var.Wait(address, cv_key, tag, ns); } + static KProcess *GetProcessFromId(u64 process_id); + static Result GetProcessList(s32 *out_num_processes, ams::kern::svc::KUserPointer out_process_ids, s32 max_out_count); + static void Switch(KProcess *cur_process, KProcess *next_process) { /* Set the current process pointer. */ SetCurrentProcess(next_process); diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 1cad4f091..2379f6b2d 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -455,4 +455,52 @@ namespace ams::kern { MESOSPHERE_UNIMPLEMENTED(); } + KProcess *KProcess::GetProcessFromId(u64 process_id) { + /* Lock the list. */ + ListAccessor accessor; + const auto end = accessor.end(); + + /* Iterate over the list. */ + for (auto it = accessor.begin(); it != end; ++it) { + /* Get the process. */ + KProcess *process = static_cast(std::addressof(*it)); + + if (process->GetId() == process_id) { + if (AMS_LIKELY(process->Open())) { + return process; + } + } + } + + /* We failed to find the process. */ + return nullptr; + } + + Result KProcess::GetProcessList(s32 *out_num_processes, ams::kern::svc::KUserPointer out_process_ids, s32 max_out_count) { + /* Lock the list. */ + ListAccessor accessor; + const auto end = accessor.end(); + + /* Iterate over the list. */ + s32 count = 0; + for (auto it = accessor.begin(); it != end; ++it) { + /* If we're within array bounds, write the id. */ + if (count < max_out_count) { + /* Get the process id. */ + KProcess *process = static_cast(std::addressof(*it)); + const u64 id = process->GetId(); + + /* Copy the id to userland. */ + R_TRY(out_process_ids.CopyArrayElementFrom(std::addressof(id), count)); + } + + /* Increment the count. */ + ++count; + } + + /* We successfully iterated the list. */ + *out_num_processes = count; + return ResultSuccess(); + } + } diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index df3f3d7f0..dedc57436 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -52,7 +52,18 @@ namespace ams::kern::svc { return ResultSuccess(); } + Result GetProcessList(int32_t *out_num_processes, KUserPointer out_process_ids, int32_t max_out_count) { + /* Validate that the out count is valid. */ + R_UNLESS((0 <= max_out_count && max_out_count <= static_cast(std::numeric_limits::max() / sizeof(u64))), svc::ResultOutOfRange()); + /* Validate that the pointer is in range. */ + if (max_out_count > 0) { + R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(out_process_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidCurrentMemory()); + } + + /* Get the process list. */ + return KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count); + } } @@ -67,7 +78,7 @@ namespace ams::kern::svc { } Result GetProcessList64(int32_t *out_num_processes, KUserPointer out_process_ids, int32_t max_out_count) { - MESOSPHERE_PANIC("Stubbed SvcGetProcessList64 was called."); + return GetProcessList(out_num_processes, out_process_ids, max_out_count); } Result CreateProcess64(ams::svc::Handle *out_handle, KUserPointer parameters, KUserPointer caps, int32_t num_caps) { @@ -97,7 +108,7 @@ namespace ams::kern::svc { } Result GetProcessList64From32(int32_t *out_num_processes, KUserPointer out_process_ids, int32_t max_out_count) { - MESOSPHERE_PANIC("Stubbed SvcGetProcessList64From32 was called."); + return GetProcessList(out_num_processes, out_process_ids, max_out_count); } Result CreateProcess64From32(ams::svc::Handle *out_handle, KUserPointer parameters, KUserPointer caps, int32_t num_caps) {