diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c index 95fcacec8..9bb4873b3 100644 --- a/exosphere/src/bootconfig.c +++ b/exosphere/src/bootconfig.c @@ -8,6 +8,8 @@ #include "fuse.h" #include "bootconfig.h" +static boot_reason_t g_boot_reason = {0}; + bool bootconfig_matches_hardware_info(void) { uint32_t hardware_info[4]; fuse_get_hardware_info(hardware_info); @@ -107,3 +109,15 @@ uint64_t bootconfig_get_kernel_memory_configuration(void) { return 0ull; } } + +void bootconfig_load_boot_reason(volatile boot_reason_t *boot_reason) { + g_boot_reason = *boot_reason; +} + +bool bootconfig_is_recovery_boot(void) { + return (g_boot_reason.is_recovery_boot != 0); +} + +uint64_t bootconfig_get_boot_reason(void) { + return ((uint64_t)g_boot_reason.boot_reason_high << 24) | (g_boot_reason.boot_reason_low & 0xFFFFFF); +} diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h index 1ceeb4b53..3a789ede0 100644 --- a/exosphere/src/bootconfig.h +++ b/exosphere/src/bootconfig.h @@ -34,9 +34,19 @@ static inline bootconfig_t *get_loaded_bootconfig(void) { return (bootconfig_t *)(TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x180); } +typedef struct { + uint64_t _0x00; + uint32_t _0x08; + uint32_t is_recovery_boot; + uint32_t boot_reason_low; + uint32_t boot_reason_high; +} boot_reason_t; + void bootconfig_load_and_verify(const bootconfig_t *bootconfig); void bootconfig_clear(void); +void bootconfig_load_boot_reason(volatile boot_reason_t *boot_reason); + /* Actual configuration getters. */ bool bootconfig_is_package2_plaintext(void); bool bootconfig_is_package2_unsigned(void); @@ -48,4 +58,7 @@ bool bootconfig_take_extabt_serror_to_el3(void); uint64_t bootconfig_get_memory_arrangement(void); uint64_t bootconfig_get_kernel_memory_configuration(void); +bool bootconfig_is_recovery_boot(void); +uint64_t bootconfig_get_boot_reason(void); + #endif diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index f367855f3..b685cb2d8 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -73,14 +73,13 @@ uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { *p_outvalue = fuse_get_retail_type(); break; case CONFIGITEM_ISRECOVERYBOOT: - /* TODO: This requires reading values passed to crt0 via NX_Bootloader. TBD pending crt0 implementation. */ - *p_outvalue = 0; + *p_outvalue = (int)(bootconfig_is_recovery_boot()); break; case CONFIGITEM_DEVICEID: *p_outvalue = fuse_get_device_id(); break; case CONFIGITEM_BOOTREASON: - /* TODO: This requires reading values passed to crt0 via NX_Bootloader. TBD pending crt0 implementation. */ + *p_outvalue = bootconfig_get_boot_reason(); break; case CONFIGITEM_MEMORYARRANGE: *p_outvalue = bootconfig_get_memory_arrangement(); diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 2a87041f4..b0c0f4ee6 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -364,7 +364,8 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { setup_current_core_state(); - /* TODO: Read and save BOOTREASON stored by NX_BOOTLOADER at 0x1F009FE00 */ + /* Save boot reason to global. */ + bootconfig_load_boot_reason((volatile boot_reason_t *)(MAILBOX_NX_BOOTLOADER_BOOT_REASON)); /* Initialize cache'd random bytes for kernel. */ randomcache_init(); diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h index c1113ecf0..b70587b79 100644 --- a/exosphere/src/package2.h +++ b/exosphere/src/package2.h @@ -31,6 +31,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) { /* Physaddr 0x40002EFC */ #define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFCULL) +#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL) + #define NX_BOOTLOADER_BOOTCONFIG_POINTER ((void *)(0x4003D000ull)) #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))