From 505324f625be87b4a37788b76cbbc8b25caafbf5 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 2 May 2019 17:55:50 -0700 Subject: [PATCH] boot: functional exception handling/rebooting to payload --- stratosphere/boot/Makefile | 23 +++++-- stratosphere/boot/source/boot_main.cpp | 6 ++ .../boot/source/boot_reboot_manager.cpp | 68 +++++++++++++++++++ .../boot/source/boot_reboot_manager.hpp | 30 ++++++++ 4 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 stratosphere/boot/source/boot_reboot_manager.cpp create mode 100644 stratosphere/boot/source/boot_reboot_manager.hpp diff --git a/stratosphere/boot/Makefile b/stratosphere/boot/Makefile index d28107e6d..7ab062393 100644 --- a/stratosphere/boot/Makefile +++ b/stratosphere/boot/Makefile @@ -16,6 +16,12 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty endif +define _bin2o + bin2s $< | $(AS) -o $(@) + echo "extern const u8" `(echo $( `(echo $(> `(echo $(> `(echo $( #include "boot_functions.hpp" +#include "boot_reboot_manager.hpp" extern "C" { extern u32 __start__; @@ -50,6 +51,11 @@ void __libnx_exception_handler(ThreadExceptionDump *ctx) { StratosphereCrashHandler(ctx); } +void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) { + /* We're boot sysmodule, so manually reboot to fatal error. */ + BootRebootManager::RebootForFatalError(ctx); +} + void __libnx_initheap(void) { void* addr = nx_inner_heap; size_t size = nx_inner_heap_size; diff --git a/stratosphere/boot/source/boot_reboot_manager.cpp b/stratosphere/boot/source/boot_reboot_manager.cpp new file mode 100644 index 000000000..e6311c3c9 --- /dev/null +++ b/stratosphere/boot/source/boot_reboot_manager.cpp @@ -0,0 +1,68 @@ +/* + * 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 . + */ + +#include +#include +#include +#include "boot_reboot_manager.hpp" +#include "fusee-primary_bin.h" + +static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); + +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_SIZE; ofs += sizeof(g_work_page)) { + CopyToIram(IRAM_BASE + ofs, g_work_page, sizeof(g_work_page)); + } +} + +static void DoRebootToPayload() { + /* Ensure clean IRAM state. */ + ClearIram(); + + /* Copy in payload. */ + for (size_t ofs = 0; ofs < fusee_primary_bin_size; ofs += 0x1000) { + std::memcpy(g_work_page, &fusee_primary_bin[ofs], std::min(static_cast(fusee_primary_bin_size - ofs), size_t(0x1000))); + CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, 0x1000); + } + + RebootToIramPayload(); +} + +Result BootRebootManager::PerformReboot() { + DoRebootToPayload(); + return ResultSuccess; +} + +void BootRebootManager::RebootForFatalError(AtmosphereFatalErrorContext *ctx) { + /* Ensure clean IRAM state. */ + ClearIram(); + + /* Copy in payload. */ + for (size_t ofs = 0; ofs < fusee_primary_bin_size; ofs += 0x1000) { + std::memcpy(g_work_page, &fusee_primary_bin[ofs], std::min(static_cast(fusee_primary_bin_size - ofs), size_t(0x1000))); + CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, 0x1000); + } + + std::memset(g_work_page, 0xCC, sizeof(g_work_page)); + std::memcpy(g_work_page, ctx, sizeof(*ctx)); + CopyToIram(IRAM_PAYLOAD_BASE + IRAM_PAYLOAD_MAX_SIZE, g_work_page, sizeof(g_work_page)); + + RebootToIramPayload(); +} \ No newline at end of file diff --git a/stratosphere/boot/source/boot_reboot_manager.hpp b/stratosphere/boot/source/boot_reboot_manager.hpp new file mode 100644 index 000000000..9b3d12046 --- /dev/null +++ b/stratosphere/boot/source/boot_reboot_manager.hpp @@ -0,0 +1,30 @@ +/* + * 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 . + */ + +#pragma once +#include +#include + +#define IRAM_BASE 0x40000000ull +#define IRAM_SIZE 0x40000 +#define IRAM_PAYLOAD_MAX_SIZE 0x2E000 +#define IRAM_PAYLOAD_BASE 0x40010000ull + +class BootRebootManager { + public: + static Result PerformReboot(); + static void RebootForFatalError(AtmosphereFatalErrorContext *ctx); +}; \ No newline at end of file