diff --git a/fusee/program/program.ld b/fusee/program/program.ld index b12f9c329..ce165ea94 100644 --- a/fusee/program/program.ld +++ b/fusee/program/program.ld @@ -22,11 +22,12 @@ SECTIONS FILL(0x00000000) KEEP(*(.text._ZN3ams4util15GetMicroSecondsEv)) KEEP(*(.text._ZN3ams4util16WaitMicroSecondsEi)) - KEEP(*(.text._ZN3ams6nxboot14ShowFatalErrorEPKcz)) - KEEP(*(.text._ZN3ams6nxboot10UncompressEPvjPKvj)) KEEP(*(.text.memcpy)) KEEP(*(.text.memset)) KEEP(*(.text.memcmp)) + KEEP(*(.text._ZN3ams6nxboot14ShowFatalErrorEPKcz)) + KEEP(*(.text._ZN3ams6nxboot10UncompressEPvjPKvj)) + KEEP(*(.text._ZN3ams6nxboot12RebootToSelfEv)) _*.o(SORT(.text*)) *(.text.unlikely .text.*_unlikely .text.unlikely.*) *(.text.exit .text.exit.*) diff --git a/fusee/program/source/fusee_exception_handler.cpp b/fusee/program/source/fusee_exception_handler.cpp index 9117cc9ac..6f71f4f87 100644 --- a/fusee/program/source/fusee_exception_handler.cpp +++ b/fusee/program/source/fusee_exception_handler.cpp @@ -15,28 +15,12 @@ */ #include #include "fusee_exception_handler.hpp" +#include "fusee_fatal.hpp" namespace ams::nxboot { - NORETURN void ErrorStop() { - /* ABORT? */ - *reinterpret_cast(0x40038000) = 0xDEADDEAD; - *reinterpret_cast(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) { - /* TODO */ - *reinterpret_cast(0x40038004) = 0xCAFEBABE; - *reinterpret_cast(0x40038008) = which; - *reinterpret_cast(0x4003800C) = lr; - *reinterpret_cast(0x40038010) = svc_lr; - ErrorStop(); + ShowFatalError("Exception: which=%" PRId32 ", lr=%p, svc_lr=%p\n", which, reinterpret_cast(lr), reinterpret_cast(svc_lr)); } } @@ -44,32 +28,39 @@ namespace ams::nxboot { namespace ams::diag { 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); - { - u32 lr; - __asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory"); - *reinterpret_cast(0x40038004) = lr; - } - ams::nxboot::ErrorStop(); + AMS_UNUSED(file, line, func, expr, format); + + u32 lr; + __asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory"); + nxboot::ShowFatalError("Abort called, lr=%p, value=%" PRIx64 "\n", reinterpret_cast(lr), value); } NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) { - AMS_UNUSED(file, line, func, expr, value); - { - u32 lr; - __asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory"); - *reinterpret_cast(0x40038004) = lr; - } - ams::nxboot::ErrorStop(); + AMS_UNUSED(file, line, func, expr); + + u32 lr; + __asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory"); + nxboot::ShowFatalError("Abort called, lr=%p, value=%" PRIx64 "\n", reinterpret_cast(lr), value); } NORETURN void AbortImpl() { - { - u32 lr; - __asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory"); - *reinterpret_cast(0x40038004) = lr; - } - ams::nxboot::ErrorStop(); + u32 lr; + __asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory"); + nxboot::ShowFatalError("Abort called, lr=%p\n", reinterpret_cast(lr)); } +} + +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); + } + } \ No newline at end of file diff --git a/fusee/program/source/fusee_fatal.cpp b/fusee/program/source/fusee_fatal.cpp index 94cf619ab..f0e45043d 100644 --- a/fusee/program/source/fusee_fatal.cpp +++ b/fusee/program/source/fusee_fatal.cpp @@ -15,12 +15,15 @@ */ #include #include "fusee_fatal.hpp" +#include "fusee_external_package.hpp" #include "fs/fusee_fs_api.hpp" namespace ams::nxboot { namespace { + constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress(); + Result SaveFatalErrorContext(const ams::impl::FatalErrorContext *ctx) { /* Create and open the 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(0x4003F000), GetExternalPackage().reboot_stub, sizeof(GetExternalPackage().reboot_stub)); + + /* Copy our main payload into low IRAM. */ + std::memcpy(reinterpret_cast(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() { /* Get the context (at static location in memory). */ ams::impl::FatalErrorContext *f_ctx = reinterpret_cast(0x4003E000); @@ -81,11 +109,16 @@ namespace ams::nxboot { AMS_INFINITE_LOOP(); } - /* TODO: Reboot to payload. */ - pmic::ShutdownSystem(true); + /* Reboot to self, if we can. */ + if (GetExternalPackage().header.magic == ExternalPackageHeader::Magic) { + RebootToSelf(); + } else { + /* Just do a normal reboot. */ + pmic::ShutdownSystem(true); - /* Wait for our reboot to complete. */ - AMS_INFINITE_LOOP(); + /* Wait for our reboot to complete. */ + AMS_INFINITE_LOOP(); + } } } diff --git a/libraries/libstratosphere/source/result/result_on_assertion.cpp b/libraries/libstratosphere/source/result/result_on_assertion.cpp index 6d4337ef5..0e7b56a53 100644 --- a/libraries/libstratosphere/source/result/result_on_assertion.cpp +++ b/libraries/libstratosphere/source/result/result_on_assertion.cpp @@ -18,7 +18,7 @@ namespace ams::result::impl { 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(); __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) { - ::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(); __builtin_unreachable(); }