From ae83ee28a3a1d31d74b991123a150d3cd202f554 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Sat, 17 Feb 2024 14:05:41 -0500
Subject: [PATCH] ns: rewrite ISystemUpdateInterface

---
 src/core/CMakeLists.txt                       |  2 +
 src/core/hle/service/ns/ns.cpp                | 41 +------------
 src/core/hle/service/ns/ns_types.h            |  6 ++
 .../service/ns/system_update_interface.cpp    | 61 +++++++++++++++++++
 .../hle/service/ns/system_update_interface.h  | 38 ++++++++++++
 5 files changed, 109 insertions(+), 39 deletions(-)
 create mode 100644 src/core/hle/service/ns/system_update_interface.cpp
 create mode 100644 src/core/hle/service/ns/system_update_interface.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index fdd1c54ac..2fb3dafd6 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -771,6 +771,8 @@ add_library(core STATIC
     hle/service/ns/read_only_application_record_interface.h
     hle/service/ns/system_update_control.cpp
     hle/service/ns/system_update_control.h
+    hle/service/ns/system_update_interface.cpp
+    hle/service/ns/system_update_interface.h
     hle/service/ns/vulnerability_manager_interface.cpp
     hle/service/ns/vulnerability_manager_interface.h
     hle/service/nvdrv/core/container.cpp
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 89700ae01..c4940db26 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -27,6 +27,7 @@
 #include "core/hle/service/ns/read_only_application_control_data_interface.h"
 #include "core/hle/service/ns/read_only_application_record_interface.h"
 #include "core/hle/service/ns/system_update_control.h"
+#include "core/hle/service/ns/system_update_interface.h"
 #include "core/hle/service/ns/vulnerability_manager_interface.h"
 #include "core/hle/service/server_manager.h"
 #include "core/hle/service/set/settings_server.h"
@@ -529,44 +530,6 @@ public:
     }
 };
 
-class NS_SU final : public ServiceFramework<NS_SU> {
-public:
-    explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, nullptr, "GetBackgroundNetworkUpdateState"},
-            {1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"},
-            {2, nullptr, "NotifyExFatDriverRequired"},
-            {3, nullptr, "ClearExFatDriverStatusForDebug"},
-            {4, nullptr, "RequestBackgroundNetworkUpdate"},
-            {5, nullptr, "NotifyBackgroundNetworkUpdate"},
-            {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
-            {9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
-            {10, nullptr, "NotifySystemUpdateForContentDelivery"},
-            {11, nullptr, "PrepareShutdown"},
-            {12, nullptr, "Unknown12"},
-            {13, nullptr, "Unknown13"},
-            {14, nullptr, "Unknown14"},
-            {15, nullptr, "Unknown15"},
-            {16, nullptr, "DestroySystemUpdateTask"},
-            {17, nullptr, "RequestSendSystemUpdate"},
-            {18, nullptr, "GetSendSystemUpdateProgress"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-
-private:
-    void OpenSystemUpdateControl(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_NS, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ISystemUpdateControl>(system);
-    }
-};
-
 void LoopProcess(Core::System& system) {
     auto server_manager = std::make_unique<ServerManager>(system);
 
@@ -578,7 +541,7 @@ void LoopProcess(Core::System& system) {
     server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system));
 
     server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system));
-    server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system));
+    server_manager->RegisterNamedService("ns:su", std::make_shared<ISystemUpdateInterface>(system));
     server_manager->RegisterNamedService("ns:vm",
                                          std::make_shared<IVulnerabilityManagerInterface>(system));
     server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system));
diff --git a/src/core/hle/service/ns/ns_types.h b/src/core/hle/service/ns/ns_types.h
index fa2aad3d9..9b6b3aa2d 100644
--- a/src/core/hle/service/ns/ns_types.h
+++ b/src/core/hle/service/ns/ns_types.h
@@ -22,6 +22,12 @@ enum class ApplicationControlSource : u8 {
     StorageOnly = 2,
 };
 
+enum class BackgroundNetworkUpdateState : u8 {
+    None,
+    InProgress,
+    Ready,
+};
+
 struct ApplicationRecord {
     u64 application_id;
     ApplicationRecordType type;
diff --git a/src/core/hle/service/ns/system_update_interface.cpp b/src/core/hle/service/ns/system_update_interface.cpp
new file mode 100644
index 000000000..7e22ca3db
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_interface.cpp
@@ -0,0 +1,61 @@
+// 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/ns/system_update_control.h"
+#include "core/hle/service/ns/system_update_interface.h"
+
+namespace Service::NS {
+
+ISystemUpdateInterface::ISystemUpdateInterface(Core::System& system_)
+    : ServiceFramework{system_, "ns:su"}, service_context{system_, "ns:su"},
+      update_notification_event{service_context} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, D<&ISystemUpdateInterface::GetBackgroundNetworkUpdateState>, "GetBackgroundNetworkUpdateState"},
+        {1, D<&ISystemUpdateInterface::OpenSystemUpdateControl>, "OpenSystemUpdateControl"},
+        {2, nullptr, "NotifyExFatDriverRequired"},
+        {3, nullptr, "ClearExFatDriverStatusForDebug"},
+        {4, nullptr, "RequestBackgroundNetworkUpdate"},
+        {5, nullptr, "NotifyBackgroundNetworkUpdate"},
+        {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
+        {9, D<&ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery>, "GetSystemUpdateNotificationEventForContentDelivery"},
+        {10, nullptr, "NotifySystemUpdateForContentDelivery"},
+        {11, nullptr, "PrepareShutdown"},
+        {12, nullptr, "Unknown12"},
+        {13, nullptr, "Unknown13"},
+        {14, nullptr, "Unknown14"},
+        {15, nullptr, "Unknown15"},
+        {16, nullptr, "DestroySystemUpdateTask"},
+        {17, nullptr, "RequestSendSystemUpdate"},
+        {18, nullptr, "GetSendSystemUpdateProgress"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+ISystemUpdateInterface::~ISystemUpdateInterface() = default;
+
+Result ISystemUpdateInterface::GetBackgroundNetworkUpdateState(
+    Out<BackgroundNetworkUpdateState> out_background_network_update_state) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+    *out_background_network_update_state = BackgroundNetworkUpdateState::None;
+    R_SUCCEED();
+}
+
+Result ISystemUpdateInterface::OpenSystemUpdateControl(
+    Out<SharedPointer<ISystemUpdateControl>> out_system_update_control) {
+    LOG_WARNING(Service_NS, "(STUBBED) called");
+    *out_system_update_control = std::make_shared<ISystemUpdateControl>(system);
+    R_SUCCEED();
+}
+
+Result ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery(
+    OutCopyHandle<Kernel::KReadableEvent> out_event) {
+    LOG_WARNING(Service_NS, "(STUBBED) called");
+    *out_event = update_notification_event.GetHandle();
+    R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_interface.h b/src/core/hle/service/ns/system_update_interface.h
new file mode 100644
index 000000000..36a2880ec
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_interface.h
@@ -0,0 +1,38 @@
+// 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/kernel_helpers.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::NS {
+
+class ISystemUpdateControl;
+
+class ISystemUpdateInterface final : public ServiceFramework<ISystemUpdateInterface> {
+public:
+    explicit ISystemUpdateInterface(Core::System& system_);
+    ~ISystemUpdateInterface() override;
+
+private:
+    Result GetBackgroundNetworkUpdateState(
+        Out<BackgroundNetworkUpdateState> out_background_network_update_state);
+    Result OpenSystemUpdateControl(
+        Out<SharedPointer<ISystemUpdateControl>> out_system_update_control);
+    Result GetSystemUpdateNotificationEventForContentDelivery(
+        OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+private:
+    KernelHelpers::ServiceContext service_context;
+    Event update_notification_event;
+};
+
+} // namespace Service::NS