From 593efedb2c106ee2f0c155d16252bbce8d68ea29 Mon Sep 17 00:00:00 2001
From: Michael Scire <SciresM@gmail.com>
Date: Thu, 3 May 2018 02:58:11 -0600
Subject: [PATCH] ProcessManager: Add BootModeInterface

---
 stratosphere/pm/source/pm_boot_mode.cpp | 33 +++++++++++++++++++++++++
 stratosphere/pm/source/pm_boot_mode.hpp | 19 ++++++++++++++
 stratosphere/pm/source/pm_main.cpp      |  7 +++++-
 3 files changed, 58 insertions(+), 1 deletion(-)
 create mode 100644 stratosphere/pm/source/pm_boot_mode.cpp
 create mode 100644 stratosphere/pm/source/pm_boot_mode.hpp

diff --git a/stratosphere/pm/source/pm_boot_mode.cpp b/stratosphere/pm/source/pm_boot_mode.cpp
new file mode 100644
index 000000000..cad3f933f
--- /dev/null
+++ b/stratosphere/pm/source/pm_boot_mode.cpp
@@ -0,0 +1,33 @@
+#include <switch.h>
+#include "pm_boot_mode.hpp"
+
+static bool g_is_maintenance_boot = false;
+
+Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
+    Result rc = 0xF601;
+    switch ((BootModeCmd)cmd_id) {
+        case BootMode_Cmd_GetBootMode:
+            rc = WrapIpcCommandImpl<&BootModeService::get_boot_mode>(this, r, out_c, pointer_buffer, pointer_buffer_size);
+            break;
+        case BootMode_Cmd_SetMaintenanceBoot:
+            rc = WrapIpcCommandImpl<&BootModeService::set_maintenance_boot>(this, r, out_c, pointer_buffer, pointer_buffer_size);
+            break;
+        default:
+            break;
+    }
+    return rc;
+}
+
+Result BootModeService::handle_deferred() {
+    /* This service is never deferrable. */
+    return 0;
+}
+
+std::tuple<Result, bool> BootModeService::get_boot_mode() {
+    return std::make_tuple(0, g_is_maintenance_boot);
+}
+
+std::tuple<Result> BootModeService::set_maintenance_boot() {
+    g_is_maintenance_boot = true;
+    return std::make_tuple(0);
+}
\ No newline at end of file
diff --git a/stratosphere/pm/source/pm_boot_mode.hpp b/stratosphere/pm/source/pm_boot_mode.hpp
new file mode 100644
index 000000000..fcbe2548c
--- /dev/null
+++ b/stratosphere/pm/source/pm_boot_mode.hpp
@@ -0,0 +1,19 @@
+#pragma once
+#include <switch.h>
+#include <stratosphere/iserviceobject.hpp>
+
+enum BootModeCmd {
+    BootMode_Cmd_GetBootMode = 0,
+    BootMode_Cmd_SetMaintenanceBoot = 1
+};
+
+class BootModeService : IServiceObject {
+    public:
+        virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
+        virtual Result handle_deferred();
+        
+    private:
+        /* Actual commands. */
+        std::tuple<Result, bool> get_boot_mode();
+        std::tuple<Result> set_maintenance_boot();
+};
\ No newline at end of file
diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp
index 51c170334..133ed17be 100644
--- a/stratosphere/pm/source/pm_main.cpp
+++ b/stratosphere/pm/source/pm_main.cpp
@@ -36,7 +36,6 @@ void __libnx_initheap(void) {
 void __appInit(void) {
     Result rc;
 
-    /* Initialize services we need (TODO: SPL) */
     rc = smInitialize();
     if (R_FAILED(rc)) {
         fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM));
@@ -56,11 +55,17 @@ void __appInit(void) {
     if (R_FAILED(rc))  {
         fatalSimple(0xCAFE << 4 | 2);
     }
+    
+    rc = splInitialize();
+    if (R_FAILED(rc))  {
+        fatalSimple(0xCAFE << 4 | 3);
+    }
 }
 
 void __appExit(void) {
     /* Cleanup services. */
     fsdevUnmountAll();
+    splExit();
     fsprExit();
     lrExit();
     fsExit();