From 1c7a7ed79ba55c5fdefd729b12d6b8aa86a0779b Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Sat, 13 Oct 2018 14:31:46 -0400
Subject: [PATCH] svc: Implement svcGetProcessInfo

A fairly basic service function, which only appears to currently support
retrieving the process state. This also alters the ProcessStatus enum to
contain all of the values that a kernel process seems to be able of
reporting with regards to state.
---
 src/core/hle/kernel/process.h  | 21 ++++++++++++++++++---
 src/core/hle/kernel/svc.cpp    | 25 ++++++++++++++++++++++++-
 src/core/hle/kernel/svc_wrap.h |  8 ++++++++
 3 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 73ec01e119..f2816943a2 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -24,6 +24,7 @@ class ProgramMetadata;
 namespace Kernel {
 
 class KernelCore;
+class ResourceLimit;
 
 struct AddressMapping {
     // Address and size must be page-aligned
@@ -57,9 +58,23 @@ union ProcessFlags {
     BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
 };
 
-enum class ProcessStatus { Created, Running, Exited };
-
-class ResourceLimit;
+/**
+ * Indicates the status of a Process instance.
+ *
+ * @note These match the values as used by kernel,
+ *       so new entries should only be added if RE
+ *       shows that a new value has been introduced.
+ */
+enum class ProcessStatus {
+    Created,
+    CreatedWithDebuggerAttached,
+    Running,
+    WaitingForDebuggerToAttach,
+    DebuggerAttached,
+    Exiting,
+    Exited,
+    DebugBreak,
+};
 
 struct CodeSet final {
     struct Segment {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index e406df829b..d9d919e181 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1092,6 +1092,29 @@ static ResultCode ClearEvent(Handle handle) {
     return RESULT_SUCCESS;
 }
 
+static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
+    LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);
+
+    // This function currently only allows retrieving a process' status.
+    enum class InfoType {
+        Status,
+    };
+
+    const auto& kernel = Core::System::GetInstance().Kernel();
+    const auto process = kernel.HandleTable().Get<Process>(process_handle);
+    if (!process) {
+        return ERR_INVALID_HANDLE;
+    }
+
+    const auto info_type = static_cast<InfoType>(type);
+    if (info_type != InfoType::Status) {
+        return ERR_INVALID_ENUM_VALUE;
+    }
+
+    *out = static_cast<u64>(process->GetStatus());
+    return RESULT_SUCCESS;
+}
+
 namespace {
 struct FunctionDef {
     using Func = void();
@@ -1227,7 +1250,7 @@ static const FunctionDef SVC_Table[] = {
     {0x79, nullptr, "CreateProcess"},
     {0x7A, nullptr, "StartProcess"},
     {0x7B, nullptr, "TerminateProcess"},
-    {0x7C, nullptr, "GetProcessInfo"},
+    {0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"},
     {0x7D, nullptr, "CreateResourceLimit"},
     {0x7E, nullptr, "SetResourceLimitLimitValue"},
     {0x7F, nullptr, "CallSecureMonitor"},
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index cbb80c3c49..b09753c80d 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -77,6 +77,14 @@ void SvcWrap() {
     FuncReturn(retval);
 }
 
+template <ResultCode func(u64*, u32, u32)>
+void SvcWrap() {
+    u64 param_1 = 0;
+    u32 retval = func(&param_1, static_cast<u32>(Param(1)), static_cast<u32>(Param(2))).raw;
+    Core::CurrentArmInterface().SetReg(1, param_1);
+    FuncReturn(retval);
+}
+
 template <ResultCode func(u32, u64)>
 void SvcWrap() {
     FuncReturn(func(static_cast<u32>(Param(0)), Param(1)).raw);