diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 389bbcaec..f03fee2bf 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -28,8 +28,9 @@ #include "exocfg.h" static bool g_battery_profile = false; +static bool g_debugmode_override_user = false, g_debugmode_override_priv = false; -uint32_t configitem_set(ConfigItem item, uint64_t value) { +uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { if (item != CONFIGITEM_BATTERYPROFILE) { return 2; } @@ -40,7 +41,7 @@ uint32_t configitem_set(ConfigItem item, uint64_t value) { bool configitem_is_recovery_boot(void) { uint64_t is_recovery_boot; - if (configitem_get(CONFIGITEM_ISRECOVERYBOOT, &is_recovery_boot) != 0) { + if (configitem_get(true, CONFIGITEM_ISRECOVERYBOOT, &is_recovery_boot) != 0) { generic_panic(); } @@ -49,7 +50,7 @@ bool configitem_is_recovery_boot(void) { bool configitem_is_retail(void) { uint64_t is_retail; - if (configitem_get(CONFIGITEM_ISRETAIL, &is_retail) != 0) { + if (configitem_get(true, CONFIGITEM_ISRETAIL, &is_retail) != 0) { generic_panic(); } @@ -62,13 +63,18 @@ bool configitem_should_profile_battery(void) { uint64_t configitem_get_hardware_type(void) { uint64_t hardware_type; - if (configitem_get(CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) { + if (configitem_get(true, CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) { generic_panic(); } return hardware_type; } -uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { +void configitem_set_debugmode_override(bool user, bool priv) { + g_debugmode_override_user = user; + g_debugmode_override_priv = priv; +} + +uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) { uint32_t result = 0; switch (item) { case CONFIGITEM_DISABLEPROGRAMVERIFICATION: @@ -109,7 +115,11 @@ uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { *p_outvalue = bootconfig_get_memory_arrangement(); break; case CONFIGITEM_ISDEBUGMODE: - *p_outvalue = (int)(bootconfig_is_debug_mode()); + if ((privileged && g_debugmode_override_priv) || (!privileged && g_debugmode_override_user)) { + *p_outvalue = 1; + } else { + *p_outvalue = (int)(bootconfig_is_debug_mode()); + } break; case CONFIGITEM_KERNELMEMORYCONFIGURATION: *p_outvalue = bootconfig_get_kernel_memory_configuration(); diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index 864d76030..f73c5469b 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -43,13 +43,15 @@ typedef enum { CONFIGITEM_EXOSPHERE_VERSION = 65000 } ConfigItem; -uint32_t configitem_set(ConfigItem item, uint64_t value); -uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue); +uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value); +uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue); bool configitem_is_recovery_boot(void); bool configitem_is_retail(void); bool configitem_should_profile_battery(void); +void configitem_set_debugmode_override(bool user, bool priv); + uint64_t configitem_get_hardware_type(void); #endif diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 10bc3ae64..77d655dd2 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -67,3 +67,19 @@ unsigned int exosphere_should_perform_620_keygen(void) { return g_exosphere_cfg.target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620 && EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_PERFORM_620_KEYGEN); } + +unsigned int exosphere_should_override_debugmode_priv(void) { + if (!g_has_loaded_config) { + generic_panic(); + } + + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV); +} + +unsigned int exosphere_should_override_debugmode_user(void) { + if (!g_has_loaded_config) { + generic_panic(); + } + + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_USER); +} diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 286825965..56ff82fdf 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -50,6 +50,8 @@ #define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) typedef struct { unsigned int magic; @@ -60,6 +62,8 @@ typedef struct { unsigned int exosphere_load_config(void); unsigned int exosphere_get_target_firmware(void); unsigned int exosphere_should_perform_620_keygen(void); +unsigned int exosphere_should_override_debugmode_priv(void); +unsigned int exosphere_should_override_debugmode_user(void); static inline unsigned int exosphere_get_target_firmware_for_init(void) { const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic; diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 706386de3..c4bed0142 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -509,6 +509,7 @@ uintptr_t get_pk2ldr_stack_address(void) { void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { /* Load Exosphere-specific config. */ exosphere_load_config(); + configitem_set_debugmode_override(exosphere_should_override_debugmode_user() != 0, exosphere_should_override_debugmode_priv() != 0); /* Setup the Security Engine. */ setup_se(); diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index f39645e47..902dd20a3 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -44,8 +44,8 @@ #define DEBUG_PANIC_ON_FAILURE 0 /* User SMC prototypes */ -uint32_t smc_set_config(smc_args_t *args); -uint32_t smc_get_config(smc_args_t *args); +uint32_t smc_set_config_user(smc_args_t *args); +uint32_t smc_get_config_user(smc_args_t *args); uint32_t smc_check_status(smc_args_t *args); uint32_t smc_get_result(smc_args_t *args); uint32_t smc_exp_mod(smc_args_t *args); @@ -71,7 +71,7 @@ uint32_t smc_decrypt_or_import_rsa_key(smc_args_t *args); uint32_t smc_cpu_suspend(smc_args_t *args); uint32_t smc_cpu_off(smc_args_t *args); uint32_t smc_cpu_on(smc_args_t *args); -/* uint32_t smc_get_config(smc_args_t *args); */ +uint32_t smc_get_config_priv(smc_args_t *args); uint32_t smc_get_random_bytes_for_priv(smc_args_t *args); uint32_t smc_panic(smc_args_t *args); uint32_t smc_configure_carveout(smc_args_t *args); @@ -89,8 +89,8 @@ typedef struct { static smc_table_entry_t g_smc_user_table[SMC_USER_HANDLERS] = { {0, NULL}, - {0xC3000401, smc_set_config}, - {0xC3000002, smc_get_config}, + {0xC3000401, smc_set_config_user}, + {0xC3000002, smc_get_config_user}, {0xC3000003, smc_check_status}, {0xC3000404, smc_get_result}, {0xC3000E05, smc_exp_mod}, @@ -114,7 +114,7 @@ static smc_table_entry_t g_smc_priv_table[SMC_PRIV_HANDLERS] = { {0xC4000001, smc_cpu_suspend}, {0x84000002, smc_cpu_off}, {0xC4000003, smc_cpu_on}, - {0xC3000004, smc_get_config}, /* NOTE: Same function as for USER */ + {0xC3000004, smc_get_config_priv}, {0xC3000005, smc_get_random_bytes_for_priv}, {0xC3000006, smc_panic}, {0xC3000007, smc_configure_carveout}, @@ -329,15 +329,15 @@ uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), return result; } -uint32_t smc_set_config(smc_args_t *args) { +uint32_t smc_set_config_user(smc_args_t *args) { /* Actual value presumed in X3 on hardware. */ - return configitem_set((ConfigItem)args->X[1], args->X[3]); + return configitem_set(false, (ConfigItem)args->X[1], args->X[3]); } -uint32_t smc_get_config(smc_args_t *args) { +uint32_t smc_get_config_user(smc_args_t *args) { uint64_t out_item = 0; uint32_t result; - result = configitem_get((ConfigItem)args->X[1], &out_item); + result = configitem_get(false, (ConfigItem)args->X[1], &out_item); args->X[1] = out_item; return result; } @@ -534,6 +534,14 @@ uint32_t smc_cpu_suspend(smc_args_t *args) { return smc_wrapper_sync(args, cpu_suspend_wrapper); } +uint32_t smc_get_config_priv(smc_args_t *args) { + uint64_t out_item = 0; + uint32_t result; + result = configitem_get(true, (ConfigItem)args->X[1], &out_item); + args->X[1] = out_item; + return result; +} + uint32_t smc_get_random_bytes_for_priv(smc_args_t *args) { /* This is an interesting SMC. */ /* The kernel must NEVER be unable to get random bytes, if it needs them */ diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index d62775834..133ebffd3 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -37,6 +37,8 @@ #define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) typedef struct { unsigned int magic; @@ -47,5 +49,7 @@ typedef struct { #define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) #define EXOSPHERE_TARGETFW_KEY "target_firmware" +#define EXOSPHERE_DEBUGMODE_PRIV_KEY "debug_mode" +#define EXOSPHERE_DEBUGMODE_USER_KEY "debug_mode_user" #endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index eec1fd2f9..eca9181c9 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -53,9 +53,26 @@ static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { exosphere_config_t *exo_cfg = (exosphere_config_t *)user; + int tmp = 0; if (strcmp(section, "exosphere") == 0) { if (strcmp(name, EXOSPHERE_TARGETFW_KEY) == 0) { sscanf(value, "%d", &exo_cfg->target_firmware); + } + if (strcmp(name, EXOSPHERE_DEBUGMODE_PRIV_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp) { + exo_cfg->flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV; + } else { + exo_cfg->flags &= ~(EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV); + } + } + if (strcmp(name, EXOSPHERE_DEBUGMODE_USER_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp) { + exo_cfg->flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_USER; + } else { + exo_cfg->flags &= ~(EXOSPHERE_FLAG_IS_DEBUGMODE_USER); + } } else { return 0; }