ams.mitm: add bpc handler, for reboot power button stuff

This commit is contained in:
Michael Scire 2019-02-04 21:17:05 -08:00
parent e715197290
commit 784964d49d
12 changed files with 226 additions and 26 deletions

View file

@ -26,7 +26,7 @@ endif
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR)) TARGET := $(notdir $(CURDIR))
BUILD := build BUILD := build
SOURCES := source source/fs_mitm source/set_mitm SOURCES := source source/fs_mitm source/set_mitm source/bpc_mitm
DATA := data DATA := data
INCLUDES := include ../../common/include INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src EXEFS_SRC := exefs_src

View file

@ -23,6 +23,7 @@
#include "fs_mitm/fsmitm_main.hpp" #include "fs_mitm/fsmitm_main.hpp"
#include "set_mitm/setmitm_main.hpp" #include "set_mitm/setmitm_main.hpp"
#include "bpc_mitm/bpcmitm_main.hpp"
static HosThread g_module_threads[MitmModuleId_Count]; static HosThread g_module_threads[MitmModuleId_Count];
@ -33,6 +34,7 @@ static const struct {
} g_module_definitions[MitmModuleId_Count] = { } g_module_definitions[MitmModuleId_Count] = {
{ &FsMitmMain, FsMitmPriority, FsMitmStackSize }, /* FsMitm */ { &FsMitmMain, FsMitmPriority, FsMitmStackSize }, /* FsMitm */
{ &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */ { &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */
{ &BpcMitmMain, BpcMitmPriority, BpcMitmStackSize }, /* BpcMitm */
}; };
void LaunchAllMitmModules() { void LaunchAllMitmModules() {

View file

@ -19,8 +19,9 @@
enum MitmModuleId : u32 { enum MitmModuleId : u32 {
MitmModuleId_FsMitm = 0, MitmModuleId_FsMitm = 0,
MitmModuleId_SetMitm = 1, MitmModuleId_SetMitm = 1,
MitmModuleId_BpcMitm = 2,
MitmModuleId_Count = 2, MitmModuleId_Count = 3,
}; };
void LaunchAllMitmModules(); void LaunchAllMitmModules();

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <mutex>
#include <switch.h>
#include <stratosphere.hpp>
#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();
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
enum BpcCmd : u32 {
BpcCmd_ShutdownSystem = 0,
BpcCmd_RebootSystem = 1,
};
class BpcMitmService : public IMitmServiceObject {
public:
BpcMitmService(std::shared_ptr<Service> 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<BpcCmd_ShutdownSystem, &BpcMitmService::ShutdownSystem>(),
MakeServiceCommandMeta<BpcCmd_RebootSystem, &BpcMitmService::RebootSystem>(),
};
};

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <malloc.h>
#include <switch.h>
#include <atmosphere.h>
#include <stratosphere.hpp>
#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<BpcMitmService>(server_manager, service_name, 13);
/* Loop forever, servicing our services. */
server_manager->Process();
delete server_manager;
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <malloc.h>
#include <switch.h>
#include <atmosphere.h>
#include <stratosphere.hpp>
constexpr u32 BpcMitmPriority = 32;
constexpr u32 BpcMitmStackSize = 0x8000;
void BpcMitmMain(void *arg);

View file

@ -17,24 +17,33 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include <string.h> #include <string.h>
#include "fatal_types.hpp" #include "bpcmitm_reboot_manager.hpp"
#include "fatal_payload_manager.hpp" #include "../utils.hpp"
/* TODO: Find a way to pre-populate this with the contents of fusee-primary. */ /* 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_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000)));
static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000)));
static bool g_payload_loaded = false; static bool g_payload_loaded = false;
static BpcRebootType g_reboot_type = BpcRebootType::ToPayload;
void FatalPayloadManager::LoadPayloadFromSdCard() { void BpcRebootManager::Initialize() {
FILE *f = fopen("sdmc:/atmosphere/reboot_payload.bin", "rb"); /* Open payload file. */
if (f == NULL) { FsFile payload_file;
if (R_FAILED(Utils::OpenSdFile("/atmosphere/reboot_payload.bin", FS_OPEN_READ, &payload_file))) {
return; 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; g_payload_loaded = true;
/* TODO: Figure out what kind of reboot we're gonna be doing. */
} }
static void ClearIram() { 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 we don't actually have a payload loaded, just go to RCM. */
if (!g_payload_loaded) { if (!g_payload_loaded) {
RebootToRcm(); RebootToRcm();
@ -63,3 +72,17 @@ void FatalPayloadManager::RebootToPayload() {
RebootToIramPayload(); 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;
}
}

View file

@ -21,8 +21,14 @@
#define IRAM_PAYLOAD_MAX_SIZE 0x2F000 #define IRAM_PAYLOAD_MAX_SIZE 0x2F000
#define IRAM_PAYLOAD_BASE 0x40010000ull #define IRAM_PAYLOAD_BASE 0x40010000ull
class FatalPayloadManager { enum class BpcRebootType : u32 {
public: Standard,
static void LoadPayloadFromSdCard(); ToRcm,
static void RebootToPayload(); ToPayload,
};
class BpcRebootManager {
public:
static void Initialize();
static Result PerformReboot();
}; };

View file

@ -29,7 +29,6 @@
#include "fatal_config.hpp" #include "fatal_config.hpp"
#include "fatal_repair.hpp" #include "fatal_repair.hpp"
#include "fatal_font.hpp" #include "fatal_font.hpp"
#include "fatal_payload_manager.hpp"
extern "C" { extern "C" {
extern u32 __start__; extern u32 __start__;
@ -160,9 +159,6 @@ int main(int argc, char **argv)
/* Load settings from set:sys. */ /* Load settings from set:sys. */
InitializeFatalConfig(); InitializeFatalConfig();
/* Load a payload from the SD card. */
FatalPayloadManager::LoadPayloadFromSdCard();
/* Load shared font. */ /* Load shared font. */
if (R_FAILED(FontManager::InitializeSharedFont())) { if (R_FAILED(FontManager::InitializeSharedFont())) {
std::abort(); std::abort();

View file

@ -16,7 +16,6 @@
#include <switch.h> #include <switch.h>
#include "fatal_task_power.hpp" #include "fatal_task_power.hpp"
#include "fatal_payload_manager.hpp"
#include "fatal_config.hpp" #include "fatal_config.hpp"
bool PowerControlTask::TryShutdown() { bool PowerControlTask::TryShutdown() {
@ -124,13 +123,11 @@ void PowerButtonObserveTask::WaitForPowerButton() {
Result rc = 0; Result rc = 0;
if (check_vol_up && R_SUCCEEDED((rc = gpioPadGetValue(&vol_up_btn, &val))) && val == GpioValue_Low) { if (check_vol_up && R_SUCCEEDED((rc = gpioPadGetValue(&vol_up_btn, &val))) && val == GpioValue_Low) {
/* Tell exosphere to reboot to payload. */ bpcRebootSystem();
FatalPayloadManager::RebootToPayload();
} }
if (check_vol_down && R_SUCCEEDED((rc = gpioPadGetValue(&vol_down_btn, &val))) && val == GpioValue_Low) { if (check_vol_down && R_SUCCEEDED((rc = gpioPadGetValue(&vol_down_btn, &val))) && val == GpioValue_Low) {
/* Tell exosphere to reboot to payload. */ bpcRebootSystem();
FatalPayloadManager::RebootToPayload();
} }
if ((R_SUCCEEDED(rc = bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) { if ((R_SUCCEEDED(rc = bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) {

View file

@ -225,8 +225,13 @@ void EmbeddedBoot2::Main() {
BootModeService::SetMaintenanceBootForEmbeddedBoot2(); BootModeService::SetMaintenanceBootForEmbeddedBoot2();
} }
/* Launch set:mitm, wait for it. */ /* Wait for other atmosphere mitm modules to initialize. */
WaitForMitm("set:sys"); WaitForMitm("set:sys");
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) {
WaitForMitm("bpc");
} else {
WaitForMitm("bpc:c");
}
/* Launch usb. */ /* Launch usb. */
LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL);