diff --git a/stratosphere/ams_mitm/Makefile b/stratosphere/ams_mitm/Makefile index 404225b..6aa64f2 100644 --- a/stratosphere/ams_mitm/Makefile +++ b/stratosphere/ams_mitm/Makefile @@ -26,7 +26,7 @@ #--------------------------------------------------------------------------------- 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 d2446b7..9d90f02 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 @@ } 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 eac0cb6..3f9d6b8 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 0000000..4860301 --- /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 0000000..ac51abe --- /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 0000000..8d9c635 --- /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 0000000..7fd1061 --- /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/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp new file mode 100644 index 0000000..12c52de --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp @@ -0,0 +1,88 @@ +/* + * 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 "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 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 { 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); + + g_payload_loaded = true; + + /* TODO: Figure out what kind of reboot we're gonna be doing. */ +} + +static void ClearIram() { + /* Make page FFs. */ + memset(g_work_page, 0xFF, sizeof(g_work_page)); + + /* Overwrite all of IRAM with FFs. */ + for (size_t ofs = 0; ofs < IRAM_PAYLOAD_MAX_SIZE; ofs += sizeof(g_work_page)) { + CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, sizeof(g_work_page)); + } +} + +static void DoRebootToPayload() { + /* If we don't actually have a payload loaded, just go to RCM. */ + if (!g_payload_loaded) { + RebootToRcm(); + } + + /* Ensure clean IRAM state. */ + ClearIram(); + + /* Copy in payload. */ + for (size_t ofs = 0; ofs < sizeof(g_reboot_payload); ofs += 0x1000) { + CopyToIram(IRAM_PAYLOAD_BASE + ofs, &g_reboot_payload[ofs], 0x1000); + } + + RebootToIramPayload(); +} + +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/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp new file mode 100644 index 0000000..d7b6c57 --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp @@ -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 . + */ + +#pragma once +#include +#include + +#define IRAM_PAYLOAD_MAX_SIZE 0x2F000 +#define IRAM_PAYLOAD_BASE 0x40010000ull + +enum class BpcRebootType : u32 { + Standard, + ToRcm, + ToPayload, +}; + +class BpcRebootManager { + public: + 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 39e5ae0..3c26538 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 @@ { /* 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_payload_manager.cpp b/stratosphere/fatal/source/fatal_payload_manager.cpp deleted file mode 100644 index 52a72d7..0000000 --- a/stratosphere/fatal/source/fatal_payload_manager.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 "fatal_types.hpp" -#include "fatal_payload_manager.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; - -void FatalPayloadManager::LoadPayloadFromSdCard() { - FILE *f = fopen("sdmc:/atmosphere/reboot_payload.bin", "rb"); - if (f == NULL) { - return; - } - ON_SCOPE_EXIT { fclose(f); }; - - memset(g_reboot_payload, 0xFF, sizeof(g_reboot_payload)); - fread(g_reboot_payload, 1, IRAM_PAYLOAD_MAX_SIZE, f); - g_payload_loaded = true; -} - -static void ClearIram() { - /* Make page FFs. */ - memset(g_work_page, 0xFF, sizeof(g_work_page)); - - /* Overwrite all of IRAM with FFs. */ - for (size_t ofs = 0; ofs < IRAM_PAYLOAD_MAX_SIZE; ofs += sizeof(g_work_page)) { - CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, sizeof(g_work_page)); - } -} - -void FatalPayloadManager::RebootToPayload() { - /* If we don't actually have a payload loaded, just go to RCM. */ - if (!g_payload_loaded) { - RebootToRcm(); - } - - /* Ensure clean IRAM state. */ - ClearIram(); - - /* Copy in payload. */ - for (size_t ofs = 0; ofs < sizeof(g_reboot_payload); ofs += 0x1000) { - CopyToIram(IRAM_PAYLOAD_BASE + ofs, &g_reboot_payload[ofs], 0x1000); - } - - RebootToIramPayload(); -} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_payload_manager.hpp b/stratosphere/fatal/source/fatal_payload_manager.hpp deleted file mode 100644 index 7aed9cd..0000000 --- a/stratosphere/fatal/source/fatal_payload_manager.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 - -#define IRAM_PAYLOAD_MAX_SIZE 0x2F000 -#define IRAM_PAYLOAD_BASE 0x40010000ull - -class FatalPayloadManager { - public: - static void LoadPayloadFromSdCard(); - static void RebootToPayload(); -}; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 4883b78..44e5b9f 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 @@ 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 6321a42..cb13a42 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -225,8 +225,13 @@ 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);