stratosphere: custom exception handlers (reboot to fusee)

This commit is contained in:
Michael Scire
2019-04-12 15:28:46 -07:00
parent b03a778611
commit ac07971211
23 changed files with 307 additions and 11 deletions

View File

@@ -71,6 +71,7 @@
"svcMapDeviceAddressSpaceAligned": "0x5a",
"svcUnmapDeviceAddressSpace": "0x5c",
"svcGetSystemInfo": "0x6f",
"svcManageNamedPort": "0x71",
"svcCallSecureMonitor": "0x7F"
}
}

View File

@@ -38,8 +38,23 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = 0x010041544D530000ul;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) {
/* We're bpc-mitm (or ams_mitm, anyway), so manually reboot to fatal error. */
Utils::RebootToFatalError(ctx);
}
void __libnx_initheap(void) {
void* addr = nx_inner_heap;

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2018-2019 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_ams_service.hpp"
#include "bpcmitm_reboot_manager.hpp"
Result BpcAtmosphereService::RebootToFatalError(InBuffer<AtmosphereFatalErrorContext> ctx) {
if (ctx.buffer == nullptr || ctx.num_elements != 1) {
return ResultKernelConnectionClosed;
}
/* Reboot to fusee with the input context. */
BpcRebootManager::RebootForFatalError(ctx.buffer);
return ResultSuccess;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2019 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>
#include "../utils.hpp"
enum BpcAtmosphereCmd : u32 {
BpcAtmosphereCmd_RebootToFatalError = 65000,
};
class BpcAtmosphereService : public IServiceObject {
private:
Result RebootToFatalError(InBuffer<AtmosphereFatalErrorContext> ctx);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<BpcAtmosphereCmd_RebootToFatalError, &BpcAtmosphereService::RebootToFatalError>(),
};
};

View File

@@ -25,7 +25,7 @@ enum BpcCmd : u32 {
BpcCmd_RebootSystem = 1,
};
class BpcMitmService : public IMitmServiceObject {
class BpcMitmService : public IMitmServiceObject {
public:
BpcMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
/* ... */

View File

@@ -25,6 +25,7 @@
#include "bpcmitm_main.hpp"
#include "bpc_mitm_service.hpp"
#include "bpc_ams_service.hpp"
#include "bpcmitm_reboot_manager.hpp"
#include "../utils.hpp"
@@ -46,6 +47,10 @@ void BpcMitmMain(void *arg) {
}
AddMitmServerToManager<BpcMitmService>(server_manager, service_name, 13);
/* Extension: Allow for reboot-to-error. */
/* Must be managed port in order for sm to be able to access. */
server_manager->AddWaitable(new ManagedPortServer<BpcAtmosphereService>("bpc:ams", 1));
/* Loop forever, servicing our services. */
server_manager->Process();

View File

@@ -64,8 +64,8 @@ static void ClearIram() {
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));
for (size_t ofs = 0; ofs < IRAM_SIZE; ofs += sizeof(g_work_page)) {
CopyToIram(IRAM_BASE + ofs, g_work_page, sizeof(g_work_page));
}
}
@@ -99,3 +99,24 @@ Result BpcRebootManager::PerformReboot() {
return ResultSuccess;
}
}
void BpcRebootManager::RebootForFatalError(AtmosphereFatalErrorContext *ctx) {
/* 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);
}
memcpy(g_work_page, ctx, sizeof(*ctx));
CopyToIram(IRAM_PAYLOAD_BASE + IRAM_PAYLOAD_MAX_SIZE, g_work_page, sizeof(g_work_page));
RebootToIramPayload();
}

View File

@@ -18,7 +18,9 @@
#include <switch.h>
#include <stratosphere.hpp>
#define IRAM_PAYLOAD_MAX_SIZE 0x2F000
#define IRAM_BASE 0x40000000ull
#define IRAM_SIZE 0x40000
#define IRAM_PAYLOAD_MAX_SIZE 0x2E000
#define IRAM_PAYLOAD_BASE 0x40010000ull
enum class BpcRebootType : u32 {
@@ -31,4 +33,5 @@ class BpcRebootManager {
public:
static void Initialize();
static Result PerformReboot();
static void RebootForFatalError(AtmosphereFatalErrorContext *ctx);
};

View File

@@ -25,6 +25,7 @@
#include "ini.h"
#include "set_mitm/setsys_settings_items.hpp"
#include "bpc_mitm/bpcmitm_reboot_manager.hpp"
static FsFileSystem g_sd_filesystem = {0};
static HosSignal g_sd_signal;
@@ -652,3 +653,7 @@ Result Utils::GetSettingsItemBooleanValue(const char *name, const char *key, boo
}
return rc;
}
void Utils::RebootToFatalError(AtmosphereFatalErrorContext *ctx) {
BpcRebootManager::RebootForFatalError(ctx);
}

View File

@@ -87,6 +87,9 @@ class Utils {
static Result GetSettingsItemValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size);
static Result GetSettingsItemBooleanValue(const char *name, const char *key, bool *out);
/* Error occurred. */
static void RebootToFatalError(AtmosphereFatalErrorContext *ctx);
private:
static void RefreshConfiguration();
};

View File

@@ -49,6 +49,17 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Boot;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}
void __libnx_initheap(void) {

View File

@@ -38,6 +38,17 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Creport;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}

View File

@@ -40,6 +40,17 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Dmnt;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}

View File

@@ -35,6 +35,17 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Eclct;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}

View File

@@ -45,6 +45,17 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Fatal;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}

View File

@@ -41,6 +41,16 @@ extern "C" {
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Loader;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}
@@ -103,9 +113,9 @@ struct LoaderServerOptions {
int main(int argc, char **argv)
{
consoleDebugInit(debugDevice_SVC);
auto server_manager = new WaitableManager<LoaderServerOptions>(1);
/* Add services to manager. */
server_manager->AddWaitable(new ServiceServer<ProcessManagerService>("ldr:pm", 1));
server_manager->AddWaitable(new ServiceServer<ShellService>("ldr:shel", 3));

View File

@@ -42,6 +42,17 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Pm;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}

View File

@@ -39,6 +39,17 @@ extern "C" {
void __libnx_initheap(void);
void __appInit(void);
void __appExit(void);
/* Exception handling. */
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
u64 __stratosphere_title_id = TitleId_Sm;
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}
@@ -73,7 +84,7 @@ int main(int argc, char **argv)
/* TODO: What's a good timeout value to use here? */
auto server_manager = new WaitableManager(1);
/* Create sm:, (and thus allow things to register to it). */
server_manager->AddWaitable(new ManagedPortServer<UserService>("sm:", 0x40));