diff --git a/stratosphere/ams_mitm/Makefile b/stratosphere/ams_mitm/Makefile
index 404225ba3..6aa64f2af 100644
--- a/stratosphere/ams_mitm/Makefile
+++ b/stratosphere/ams_mitm/Makefile
@@ -26,7 +26,7 @@ endif
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
-SOURCES := source source/fs_mitm source/set_mitm
+SOURCES := source source/fs_mitm source/set_mitm source/bpc_mitm
DATA := data
INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src
diff --git a/stratosphere/ams_mitm/source/amsmitm_modules.cpp b/stratosphere/ams_mitm/source/amsmitm_modules.cpp
index d2446b77a..9d90f02b7 100644
--- a/stratosphere/ams_mitm/source/amsmitm_modules.cpp
+++ b/stratosphere/ams_mitm/source/amsmitm_modules.cpp
@@ -23,6 +23,7 @@
#include "fs_mitm/fsmitm_main.hpp"
#include "set_mitm/setmitm_main.hpp"
+#include "bpc_mitm/bpcmitm_main.hpp"
static HosThread g_module_threads[MitmModuleId_Count];
@@ -33,6 +34,7 @@ static const struct {
} g_module_definitions[MitmModuleId_Count] = {
{ &FsMitmMain, FsMitmPriority, FsMitmStackSize }, /* FsMitm */
{ &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */
+ { &BpcMitmMain, BpcMitmPriority, BpcMitmStackSize }, /* BpcMitm */
};
void LaunchAllMitmModules() {
diff --git a/stratosphere/ams_mitm/source/amsmitm_modules.hpp b/stratosphere/ams_mitm/source/amsmitm_modules.hpp
index eac0cb6fe..3f9d6b830 100644
--- a/stratosphere/ams_mitm/source/amsmitm_modules.hpp
+++ b/stratosphere/ams_mitm/source/amsmitm_modules.hpp
@@ -19,8 +19,9 @@
enum MitmModuleId : u32 {
MitmModuleId_FsMitm = 0,
MitmModuleId_SetMitm = 1,
+ MitmModuleId_BpcMitm = 2,
- MitmModuleId_Count = 2,
+ MitmModuleId_Count = 3,
};
void LaunchAllMitmModules();
diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp
new file mode 100644
index 000000000..4860301e4
--- /dev/null
+++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include "bpc_mitm_service.hpp"
+#include "bpcmitm_reboot_manager.hpp"
+
+void BpcMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
+ /* Nothing to do here */
+}
+
+Result BpcMitmService::ShutdownSystem() {
+ /* TODO: Use exosphere + reboot to perform real shutdown, instead of fake shutdown. */
+ return RESULT_FORWARD_TO_SESSION;
+}
+
+Result BpcMitmService::RebootSystem() {
+ return BpcRebootManager::PerformReboot();
+}
diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp
new file mode 100644
index 000000000..ac51abe8f
--- /dev/null
+++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+
+enum BpcCmd : u32 {
+ BpcCmd_ShutdownSystem = 0,
+ BpcCmd_RebootSystem = 1,
+};
+
+class BpcMitmService : public IMitmServiceObject {
+ public:
+ BpcMitmService(std::shared_ptr s, u64 pid) : IMitmServiceObject(s, pid) {
+ /* ... */
+ }
+
+ static bool ShouldMitm(u64 pid, u64 tid) {
+ /* We will mitm:
+ * - am, to intercept the Reboot/Power buttons in the overlay menu.
+ * - fatal, to simplify payload reboot logic significantly
+ * - applications, to allow homebrew to take advantage of the feature.
+ */
+ return tid == 0x0100000000000023ull || tid == 0x0100000000000034ull || tid >= 0x0100000000010000ull;
+ }
+
+ static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx);
+
+ protected:
+ /* Overridden commands. */
+ Result ShutdownSystem();
+ Result RebootSystem();
+ public:
+ DEFINE_SERVICE_DISPATCH_TABLE {
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ };
+};
diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp
new file mode 100644
index 000000000..8d9c63530
--- /dev/null
+++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "bpcmitm_main.hpp"
+#include "bpc_mitm_service.hpp"
+#include "bpcmitm_reboot_manager.hpp"
+
+#include "../utils.hpp"
+
+void BpcMitmMain(void *arg) {
+ /* Wait for initialization to occur */
+ Utils::WaitSdInitialized();
+
+ /* Load a payload off of the SD */
+ BpcRebootManager::Initialize();
+
+ /* Create server manager */
+ auto server_manager = new WaitableManager(2);
+
+ /* Create bpc mitm. */
+ const char *service_name = "bpc";
+ if (GetRuntimeFirmwareVersion() < FirmwareVersion_200) {
+ service_name = "bpc:c";
+ }
+ AddMitmServerToManager(server_manager, service_name, 13);
+
+ /* Loop forever, servicing our services. */
+ server_manager->Process();
+
+ delete server_manager;
+
+}
+
diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.hpp
new file mode 100644
index 000000000..7fd1061a0
--- /dev/null
+++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.hpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+constexpr u32 BpcMitmPriority = 32;
+constexpr u32 BpcMitmStackSize = 0x8000;
+
+void BpcMitmMain(void *arg);
\ No newline at end of file
diff --git a/stratosphere/fatal/source/fatal_payload_manager.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp
similarity index 61%
rename from stratosphere/fatal/source/fatal_payload_manager.cpp
rename to stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp
index 52a72d7d6..12c52def9 100644
--- a/stratosphere/fatal/source/fatal_payload_manager.cpp
+++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp
@@ -17,24 +17,33 @@
#include
#include
#include
-#include "fatal_types.hpp"
-#include "fatal_payload_manager.hpp"
+#include "bpcmitm_reboot_manager.hpp"
+#include "../utils.hpp"
/* TODO: Find a way to pre-populate this with the contents of fusee-primary. */
static u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000)));
static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000)));
static bool g_payload_loaded = false;
+static BpcRebootType g_reboot_type = BpcRebootType::ToPayload;
-void FatalPayloadManager::LoadPayloadFromSdCard() {
- FILE *f = fopen("sdmc:/atmosphere/reboot_payload.bin", "rb");
- if (f == NULL) {
+void BpcRebootManager::Initialize() {
+ /* Open payload file. */
+ FsFile payload_file;
+ if (R_FAILED(Utils::OpenSdFile("/atmosphere/reboot_payload.bin", FS_OPEN_READ, &payload_file))) {
return;
}
- ON_SCOPE_EXIT { fclose(f); };
+ ON_SCOPE_EXIT { fsFileClose(&payload_file); };
+
+ /* Clear payload buffer */
+ std::memset(g_reboot_payload, 0xFF, sizeof(g_reboot_payload));
+
+ /* Read payload file. */
+ size_t actual_size;
+ fsFileRead(&payload_file, 0, g_reboot_payload, IRAM_PAYLOAD_MAX_SIZE, &actual_size);
- memset(g_reboot_payload, 0xFF, sizeof(g_reboot_payload));
- fread(g_reboot_payload, 1, IRAM_PAYLOAD_MAX_SIZE, f);
g_payload_loaded = true;
+
+ /* TODO: Figure out what kind of reboot we're gonna be doing. */
}
static void ClearIram() {
@@ -47,7 +56,7 @@ static void ClearIram() {
}
}
-void FatalPayloadManager::RebootToPayload() {
+static void DoRebootToPayload() {
/* If we don't actually have a payload loaded, just go to RCM. */
if (!g_payload_loaded) {
RebootToRcm();
@@ -62,4 +71,18 @@ void FatalPayloadManager::RebootToPayload() {
}
RebootToIramPayload();
-}
\ No newline at end of file
+}
+
+Result BpcRebootManager::PerformReboot() {
+ switch (g_reboot_type) {
+ case BpcRebootType::Standard:
+ return RESULT_FORWARD_TO_SESSION;
+ case BpcRebootType::ToRcm:
+ RebootToRcm();
+ return 0;
+ case BpcRebootType::ToPayload:
+ default:
+ DoRebootToPayload();
+ return 0;
+ }
+}
diff --git a/stratosphere/fatal/source/fatal_payload_manager.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp
similarity index 81%
rename from stratosphere/fatal/source/fatal_payload_manager.hpp
rename to stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp
index 7aed9cdce..d7b6c575c 100644
--- a/stratosphere/fatal/source/fatal_payload_manager.hpp
+++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp
@@ -21,8 +21,14 @@
#define IRAM_PAYLOAD_MAX_SIZE 0x2F000
#define IRAM_PAYLOAD_BASE 0x40010000ull
-class FatalPayloadManager {
+enum class BpcRebootType : u32 {
+ Standard,
+ ToRcm,
+ ToPayload,
+};
+
+class BpcRebootManager {
public:
- static void LoadPayloadFromSdCard();
- static void RebootToPayload();
+ static void Initialize();
+ static Result PerformReboot();
};
\ No newline at end of file
diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp
index 39e5ae088..3c26538c2 100644
--- a/stratosphere/fatal/source/fatal_main.cpp
+++ b/stratosphere/fatal/source/fatal_main.cpp
@@ -29,7 +29,6 @@
#include "fatal_config.hpp"
#include "fatal_repair.hpp"
#include "fatal_font.hpp"
-#include "fatal_payload_manager.hpp"
extern "C" {
extern u32 __start__;
@@ -159,10 +158,7 @@ int main(int argc, char **argv)
{
/* Load settings from set:sys. */
InitializeFatalConfig();
-
- /* Load a payload from the SD card. */
- FatalPayloadManager::LoadPayloadFromSdCard();
-
+
/* Load shared font. */
if (R_FAILED(FontManager::InitializeSharedFont())) {
std::abort();
diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp
index 4883b78f7..44e5b9f2e 100644
--- a/stratosphere/fatal/source/fatal_task_power.cpp
+++ b/stratosphere/fatal/source/fatal_task_power.cpp
@@ -16,7 +16,6 @@
#include
#include "fatal_task_power.hpp"
-#include "fatal_payload_manager.hpp"
#include "fatal_config.hpp"
bool PowerControlTask::TryShutdown() {
@@ -124,13 +123,11 @@ void PowerButtonObserveTask::WaitForPowerButton() {
Result rc = 0;
if (check_vol_up && R_SUCCEEDED((rc = gpioPadGetValue(&vol_up_btn, &val))) && val == GpioValue_Low) {
- /* Tell exosphere to reboot to payload. */
- FatalPayloadManager::RebootToPayload();
+ bpcRebootSystem();
}
if (check_vol_down && R_SUCCEEDED((rc = gpioPadGetValue(&vol_down_btn, &val))) && val == GpioValue_Low) {
- /* Tell exosphere to reboot to payload. */
- FatalPayloadManager::RebootToPayload();
+ bpcRebootSystem();
}
if ((R_SUCCEEDED(rc = bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) {
diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp
index 6321a42f7..cb13a42ac 100644
--- a/stratosphere/pm/source/pm_boot2.cpp
+++ b/stratosphere/pm/source/pm_boot2.cpp
@@ -225,8 +225,13 @@ void EmbeddedBoot2::Main() {
BootModeService::SetMaintenanceBootForEmbeddedBoot2();
}
- /* Launch set:mitm, wait for it. */
+ /* Wait for other atmosphere mitm modules to initialize. */
WaitForMitm("set:sys");
+ if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) {
+ WaitForMitm("bpc");
+ } else {
+ WaitForMitm("bpc:c");
+ }
/* Launch usb. */
LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL);