From 66b3b3a7064dfd1f5739c97df207e51929eea889 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 27 Feb 2018 19:43:07 -0800 Subject: [PATCH] Implement Panic() stub. --- exosphere/src/pmc.h | 5 +++++ exosphere/src/smc_api.c | 6 +++--- exosphere/src/timers.c | 17 +++++++++++++++++ exosphere/src/timers.h | 13 +++++++++++++ exosphere/src/utils.c | 23 +++++++++++++++++++---- exosphere/src/utils.h | 4 ++-- 6 files changed, 59 insertions(+), 9 deletions(-) diff --git a/exosphere/src/pmc.h b/exosphere/src/pmc.h index 6c1d78399..0d28d40f9 100644 --- a/exosphere/src/pmc.h +++ b/exosphere/src/pmc.h @@ -19,6 +19,8 @@ static inline uintptr_t get_pmc_base(void) { #define APBDEV_PMC_SCRATCH0_0 (*((volatile uint32_t *)(PMC_BASE + 0x50))) +#define APBDEV_PMC_CRYPTO_OP_0 (*((volatile uint32_t *)(PMC_BASE + 0xF4))) + #define APBDEV_PM_0 (*((volatile uint32_t *)(PMC_BASE + 0x14))) #define APBDEV_PMC_WAKE2_STATUS_0 (*((volatile uint32_t *)(PMC_BASE + 0x168))) #define APBDEV_PMC_CNTRL2_0 (*((volatile uint32_t *)(PMC_BASE + 0x440))) @@ -30,5 +32,8 @@ static inline uintptr_t get_pmc_base(void) { #define APBDEV_PMC_SECURE_SCRATCH114_0 (*((volatile uint32_t *)(PMC_BASE + 0xB20))) #define APBDEV_PMC_SECURE_SCRATCH115_0 (*((volatile uint32_t *)(PMC_BASE + 0xB24))) +#define APBDEV_PMC_SCRATCH200_0 (*((volatile uint32_t *)(PMC_BASE + 0x840))) + + #endif diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index 787babd59..f801c388d 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -566,7 +566,7 @@ uint32_t smc_configure_carveout(smc_args_t *args) { } uint32_t smc_panic(smc_args_t *args) { - (void)args; - return 0; - /* TODO */ + /* Swap RGB values from args. */ + uint32_t color = ((args->X[1] & 0xF) << 8) | ((args->X[1] & 0xF0)) | ((args->X[1] & 0xF00) >> 8); + panic((color << 20) | 0x40); } diff --git a/exosphere/src/timers.c b/exosphere/src/timers.c index b339a401f..cf16fef5f 100644 --- a/exosphere/src/timers.c +++ b/exosphere/src/timers.c @@ -1,3 +1,7 @@ +#include +#include + +#include "utils.h" #include "timers.h" void wait(uint32_t microseconds) { @@ -5,4 +9,17 @@ void wait(uint32_t microseconds) { while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { /* Spin-lock. */ } +} + +__attribute__ ((noreturn)) void watchdog_reboot(void) { + unsigned int current_core = get_core_id(); + volatile watchdog_timers_t *wdt = GET_WDT(current_core); + wdt->PATTERN = WDT_REBOOT_PATTERN; + wdt->COMMAND = 2; /* Disable Counter. */ + GET_WDT_REBOOT_CFG_REG(current_core) = 0xC0000000; + wdt->CONFIG = 0x8015 + current_core; /* Full System Reset after Fourth Counter expires, using TIMER(5+core_id). */ + wdt->COMMAND = 1; /* Enable Counter. */ + while (true) { + /* Wait for reboot. */ + } } \ No newline at end of file diff --git a/exosphere/src/timers.h b/exosphere/src/timers.h index 2f71039d8..f7480f8d2 100644 --- a/exosphere/src/timers.h +++ b/exosphere/src/timers.h @@ -14,10 +14,23 @@ static inline uintptr_t get_timers_base(void) { #define TIMERUS_CNTR_1US_0 (*((volatile uint32_t *)(TIMERS_BASE + 0x10))) +typedef struct { + uint32_t CONFIG; + uint32_t STATUS; + uint32_t COMMAND; + uint32_t PATTERN; +} watchdog_timers_t; + +#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) +#define WDT_REBOOT_PATTERN 0xC45A +#define GET_WDT_REBOOT_CFG_REG(n) (*((volatile uint32_t *)(TIMERS_BASE + 0x60 + 0x8*n))) + void wait(uint32_t microseconds); static inline uint32_t get_time(void) { return TIMERUS_CNTR_1US_0; } +__attribute__ ((noreturn)) void watchdog_reboot(void); + #endif diff --git a/exosphere/src/utils.c b/exosphere/src/utils.c index 2a8bbadac..375d20f02 100644 --- a/exosphere/src/utils.c +++ b/exosphere/src/utils.c @@ -1,11 +1,26 @@ +#include #include "utils.h" +#include "se.h" +#include "fuse.h" +#include "pmc.h" +#include "timers.h" -void panic(uint32_t code) { - (void)code; /* TODO */ + +__attribute__ ((noreturn)) void panic(uint32_t code) { + /* Set Panic Code for NX_BOOTLOADER. */ + if (APBDEV_PMC_SCRATCH200_0 == 0) { + APBDEV_PMC_SCRATCH200_0 = code; + } + + /* TODO: Custom Panic Driver, which displays to screen without rebooting. */ + /* For now, just use NX BOOTLOADER's panic. */ + fuse_disable_programming(); + APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */ + watchdog_reboot(); } -void generic_panic(void) { - /* TODO */ +__attribute__ ((noreturn)) void generic_panic(void) { + panic(0xFF000006); } __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be) diff --git a/exosphere/src/utils.h b/exosphere/src/utils.h index c40e7ef75..2eddff5cb 100644 --- a/exosphere/src/utils.h +++ b/exosphere/src/utils.h @@ -13,8 +13,8 @@ #define ALINLINE __attribute__((always_inline)) -void panic(uint32_t code); -void generic_panic(void); +__attribute__ ((noreturn)) void panic(uint32_t code); +__attribute__ ((noreturn)) void generic_panic(void); bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be); static inline uintptr_t get_physical_address(const void *vaddr) {