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);