mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
fusee: attempt reboot to self if possible, better abort/fatal handlers
This commit is contained in:
parent
005aac5a2b
commit
dda7ea6ac2
4 changed files with 71 additions and 46 deletions
|
@ -22,11 +22,12 @@ SECTIONS
|
||||||
FILL(0x00000000)
|
FILL(0x00000000)
|
||||||
KEEP(*(.text._ZN3ams4util15GetMicroSecondsEv))
|
KEEP(*(.text._ZN3ams4util15GetMicroSecondsEv))
|
||||||
KEEP(*(.text._ZN3ams4util16WaitMicroSecondsEi))
|
KEEP(*(.text._ZN3ams4util16WaitMicroSecondsEi))
|
||||||
KEEP(*(.text._ZN3ams6nxboot14ShowFatalErrorEPKcz))
|
|
||||||
KEEP(*(.text._ZN3ams6nxboot10UncompressEPvjPKvj))
|
|
||||||
KEEP(*(.text.memcpy))
|
KEEP(*(.text.memcpy))
|
||||||
KEEP(*(.text.memset))
|
KEEP(*(.text.memset))
|
||||||
KEEP(*(.text.memcmp))
|
KEEP(*(.text.memcmp))
|
||||||
|
KEEP(*(.text._ZN3ams6nxboot14ShowFatalErrorEPKcz))
|
||||||
|
KEEP(*(.text._ZN3ams6nxboot10UncompressEPvjPKvj))
|
||||||
|
KEEP(*(.text._ZN3ams6nxboot12RebootToSelfEv))
|
||||||
_*.o(SORT(.text*))
|
_*.o(SORT(.text*))
|
||||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
*(.text.exit .text.exit.*)
|
*(.text.exit .text.exit.*)
|
||||||
|
|
|
@ -15,28 +15,12 @@
|
||||||
*/
|
*/
|
||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
#include "fusee_exception_handler.hpp"
|
#include "fusee_exception_handler.hpp"
|
||||||
|
#include "fusee_fatal.hpp"
|
||||||
|
|
||||||
namespace ams::nxboot {
|
namespace ams::nxboot {
|
||||||
|
|
||||||
NORETURN void ErrorStop() {
|
|
||||||
/* ABORT? */
|
|
||||||
*reinterpret_cast<volatile u32 *>(0x40038000) = 0xDEADDEAD;
|
|
||||||
*reinterpret_cast<volatile u32 *>(0x7000E400) = 0x10;
|
|
||||||
|
|
||||||
/* Halt ourselves. */
|
|
||||||
while (true) {
|
|
||||||
reg::Write(secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress() + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
|
|
||||||
FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_JTAG, ENABLED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NORETURN void ExceptionHandlerImpl(s32 which, u32 lr, u32 svc_lr) {
|
NORETURN void ExceptionHandlerImpl(s32 which, u32 lr, u32 svc_lr) {
|
||||||
/* TODO */
|
ShowFatalError("Exception: which=%" PRId32 ", lr=%p, svc_lr=%p\n", which, reinterpret_cast<void *>(lr), reinterpret_cast<void *>(svc_lr));
|
||||||
*reinterpret_cast<volatile u32 *>(0x40038004) = 0xCAFEBABE;
|
|
||||||
*reinterpret_cast<volatile u32 *>(0x40038008) = which;
|
|
||||||
*reinterpret_cast<volatile u32 *>(0x4003800C) = lr;
|
|
||||||
*reinterpret_cast<volatile u32 *>(0x40038010) = svc_lr;
|
|
||||||
ErrorStop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,32 +28,39 @@ namespace ams::nxboot {
|
||||||
namespace ams::diag {
|
namespace ams::diag {
|
||||||
|
|
||||||
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) {
|
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) {
|
||||||
AMS_UNUSED(file, line, func, expr, value, format);
|
AMS_UNUSED(file, line, func, expr, format);
|
||||||
{
|
|
||||||
u32 lr;
|
u32 lr;
|
||||||
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
|
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
|
||||||
*reinterpret_cast<volatile u32 *>(0x40038004) = lr;
|
nxboot::ShowFatalError("Abort called, lr=%p, value=%" PRIx64 "\n", reinterpret_cast<void *>(lr), value);
|
||||||
}
|
|
||||||
ams::nxboot::ErrorStop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) {
|
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) {
|
||||||
AMS_UNUSED(file, line, func, expr, value);
|
AMS_UNUSED(file, line, func, expr);
|
||||||
{
|
|
||||||
u32 lr;
|
u32 lr;
|
||||||
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
|
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
|
||||||
*reinterpret_cast<volatile u32 *>(0x40038004) = lr;
|
nxboot::ShowFatalError("Abort called, lr=%p, value=%" PRIx64 "\n", reinterpret_cast<void *>(lr), value);
|
||||||
}
|
|
||||||
ams::nxboot::ErrorStop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN void AbortImpl() {
|
NORETURN void AbortImpl() {
|
||||||
{
|
|
||||||
u32 lr;
|
u32 lr;
|
||||||
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
|
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
|
||||||
*reinterpret_cast<volatile u32 *>(0x40038004) = lr;
|
nxboot::ShowFatalError("Abort called, lr=%p\n", reinterpret_cast<void *>(lr));
|
||||||
}
|
}
|
||||||
ams::nxboot::ErrorStop();
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ams::result::impl {
|
||||||
|
|
||||||
|
NORETURN void OnResultAbort(const char *file, int line, const char *func, const char *expr, Result result) {
|
||||||
|
::ams::diag::AbortImpl(file, line, func, expr, result.GetValue(), "Result Abort: 2%03" PRId32 "-%04" PRId32 "", result.GetModule(), result.GetDescription());
|
||||||
|
AMS_INFINITE_LOOP();
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void OnResultAbort(Result result) {
|
||||||
|
OnResultAbort("", 0, "", "", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,12 +15,15 @@
|
||||||
*/
|
*/
|
||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
#include "fusee_fatal.hpp"
|
#include "fusee_fatal.hpp"
|
||||||
|
#include "fusee_external_package.hpp"
|
||||||
#include "fs/fusee_fs_api.hpp"
|
#include "fs/fusee_fs_api.hpp"
|
||||||
|
|
||||||
namespace ams::nxboot {
|
namespace ams::nxboot {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
|
||||||
Result SaveFatalErrorContext(const ams::impl::FatalErrorContext *ctx) {
|
Result SaveFatalErrorContext(const ams::impl::FatalErrorContext *ctx) {
|
||||||
/* Create and open the file. */
|
/* Create and open the file. */
|
||||||
fs::FileHandle file;
|
fs::FileHandle file;
|
||||||
|
@ -47,6 +50,31 @@ namespace ams::nxboot {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NORETURN void RebootToSelf() {
|
||||||
|
/* Patch SDRAM init to perform an SVC immediately after second write. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SCRATCH45, 0x2E38DFFF);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SCRATCH46, 0x6001DC28);
|
||||||
|
|
||||||
|
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SCRATCH33, 0x4003F000);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SCRATCH40, 0x6000F208);
|
||||||
|
|
||||||
|
/* Set boot as warmboot. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SCRATCH0, (1 << 0));
|
||||||
|
|
||||||
|
/* Copy reboot stub into high IRAM. */
|
||||||
|
std::memcpy(reinterpret_cast<void *>(0x4003F000), GetExternalPackage().reboot_stub, sizeof(GetExternalPackage().reboot_stub));
|
||||||
|
|
||||||
|
/* Copy our main payload into low IRAM. */
|
||||||
|
std::memcpy(reinterpret_cast<void *>(0x40010000), GetExternalPackage().fusee, sizeof(GetExternalPackage().fusee));
|
||||||
|
|
||||||
|
/* Reboot. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
|
||||||
|
|
||||||
|
/* Wait for the reboot to take. */
|
||||||
|
AMS_INFINITE_LOOP();
|
||||||
|
}
|
||||||
|
|
||||||
void SaveAndShowFatalError() {
|
void SaveAndShowFatalError() {
|
||||||
/* Get the context (at static location in memory). */
|
/* Get the context (at static location in memory). */
|
||||||
ams::impl::FatalErrorContext *f_ctx = reinterpret_cast<ams::impl::FatalErrorContext *>(0x4003E000);
|
ams::impl::FatalErrorContext *f_ctx = reinterpret_cast<ams::impl::FatalErrorContext *>(0x4003E000);
|
||||||
|
@ -81,11 +109,16 @@ namespace ams::nxboot {
|
||||||
AMS_INFINITE_LOOP();
|
AMS_INFINITE_LOOP();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Reboot to payload. */
|
/* Reboot to self, if we can. */
|
||||||
|
if (GetExternalPackage().header.magic == ExternalPackageHeader::Magic) {
|
||||||
|
RebootToSelf();
|
||||||
|
} else {
|
||||||
|
/* Just do a normal reboot. */
|
||||||
pmic::ShutdownSystem(true);
|
pmic::ShutdownSystem(true);
|
||||||
|
|
||||||
/* Wait for our reboot to complete. */
|
/* Wait for our reboot to complete. */
|
||||||
AMS_INFINITE_LOOP();
|
AMS_INFINITE_LOOP();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
namespace ams::result::impl {
|
namespace ams::result::impl {
|
||||||
|
|
||||||
NORETURN WEAK_SYMBOL void OnResultAbort(const char *file, int line, const char *func, const char *expr, Result result) {
|
NORETURN WEAK_SYMBOL void OnResultAbort(const char *file, int line, const char *func, const char *expr, Result result) {
|
||||||
::ams::diag::AbortImpl(file, line, func, expr, result.GetValue(), "Result Abort: %203d-%04d", result.GetModule(), result.GetDescription());
|
::ams::diag::AbortImpl(file, line, func, expr, result.GetValue(), "Result Abort: 2%03d-%04d", result.GetModule(), result.GetDescription());
|
||||||
AMS_INFINITE_LOOP();
|
AMS_INFINITE_LOOP();
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ namespace ams::result::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN WEAK_SYMBOL void OnResultAssertion(const char *file, int line, const char *func, const char *expr, Result result) {
|
NORETURN WEAK_SYMBOL void OnResultAssertion(const char *file, int line, const char *func, const char *expr, Result result) {
|
||||||
::ams::diag::AssertionFailureImpl(file, line, func, expr, result.GetValue(), "Result Assertion: %203d-%04d", result.GetModule(), result.GetDescription());
|
::ams::diag::AssertionFailureImpl(file, line, func, expr, result.GetValue(), "Result Assertion: 2%03d-%04d", result.GetModule(), result.GetDescription());
|
||||||
AMS_INFINITE_LOOP();
|
AMS_INFINITE_LOOP();
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue