exosphere: Add support for enabling debugmode via BCT.ini

This commit is contained in:
Michael Scire 2018-11-30 03:10:27 -08:00
parent 49ad66e478
commit 72a2c10896
8 changed files with 80 additions and 18 deletions

View file

@ -28,8 +28,9 @@
#include "exocfg.h" #include "exocfg.h"
static bool g_battery_profile = false; 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) { if (item != CONFIGITEM_BATTERYPROFILE) {
return 2; return 2;
} }
@ -40,7 +41,7 @@ uint32_t configitem_set(ConfigItem item, uint64_t value) {
bool configitem_is_recovery_boot(void) { bool configitem_is_recovery_boot(void) {
uint64_t is_recovery_boot; 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(); generic_panic();
} }
@ -49,7 +50,7 @@ bool configitem_is_recovery_boot(void) {
bool configitem_is_retail(void) { bool configitem_is_retail(void) {
uint64_t is_retail; uint64_t is_retail;
if (configitem_get(CONFIGITEM_ISRETAIL, &is_retail) != 0) { if (configitem_get(true, CONFIGITEM_ISRETAIL, &is_retail) != 0) {
generic_panic(); generic_panic();
} }
@ -62,13 +63,18 @@ bool configitem_should_profile_battery(void) {
uint64_t configitem_get_hardware_type(void) { uint64_t configitem_get_hardware_type(void) {
uint64_t hardware_type; uint64_t hardware_type;
if (configitem_get(CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) { if (configitem_get(true, CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) {
generic_panic(); generic_panic();
} }
return hardware_type; 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; uint32_t result = 0;
switch (item) { switch (item) {
case CONFIGITEM_DISABLEPROGRAMVERIFICATION: case CONFIGITEM_DISABLEPROGRAMVERIFICATION:
@ -109,7 +115,11 @@ uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) {
*p_outvalue = bootconfig_get_memory_arrangement(); *p_outvalue = bootconfig_get_memory_arrangement();
break; break;
case CONFIGITEM_ISDEBUGMODE: 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; break;
case CONFIGITEM_KERNELMEMORYCONFIGURATION: case CONFIGITEM_KERNELMEMORYCONFIGURATION:
*p_outvalue = bootconfig_get_kernel_memory_configuration(); *p_outvalue = bootconfig_get_kernel_memory_configuration();

View file

@ -43,13 +43,15 @@ typedef enum {
CONFIGITEM_EXOSPHERE_VERSION = 65000 CONFIGITEM_EXOSPHERE_VERSION = 65000
} ConfigItem; } ConfigItem;
uint32_t configitem_set(ConfigItem item, uint64_t value); uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value);
uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue); uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue);
bool configitem_is_recovery_boot(void); bool configitem_is_recovery_boot(void);
bool configitem_is_retail(void); bool configitem_is_retail(void);
bool configitem_should_profile_battery(void); bool configitem_should_profile_battery(void);
void configitem_set_debugmode_override(bool user, bool priv);
uint64_t configitem_get_hardware_type(void); uint64_t configitem_get_hardware_type(void);
#endif #endif

View file

@ -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); 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);
}

View file

@ -50,6 +50,8 @@
#define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAGS_DEFAULT 0x00000000
#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) #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 { typedef struct {
unsigned int magic; unsigned int magic;
@ -60,6 +62,8 @@ typedef struct {
unsigned int exosphere_load_config(void); unsigned int exosphere_load_config(void);
unsigned int exosphere_get_target_firmware(void); unsigned int exosphere_get_target_firmware(void);
unsigned int exosphere_should_perform_620_keygen(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) { static inline unsigned int exosphere_get_target_firmware_for_init(void) {
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic; const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic;

View file

@ -509,6 +509,7 @@ uintptr_t get_pk2ldr_stack_address(void) {
void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
/* Load Exosphere-specific config. */ /* Load Exosphere-specific config. */
exosphere_load_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 the Security Engine. */
setup_se(); setup_se();

View file

@ -44,8 +44,8 @@
#define DEBUG_PANIC_ON_FAILURE 0 #define DEBUG_PANIC_ON_FAILURE 0
/* User SMC prototypes */ /* User SMC prototypes */
uint32_t smc_set_config(smc_args_t *args); uint32_t smc_set_config_user(smc_args_t *args);
uint32_t smc_get_config(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_check_status(smc_args_t *args);
uint32_t smc_get_result(smc_args_t *args); uint32_t smc_get_result(smc_args_t *args);
uint32_t smc_exp_mod(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_suspend(smc_args_t *args);
uint32_t smc_cpu_off(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_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_get_random_bytes_for_priv(smc_args_t *args);
uint32_t smc_panic(smc_args_t *args); uint32_t smc_panic(smc_args_t *args);
uint32_t smc_configure_carveout(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] = { static smc_table_entry_t g_smc_user_table[SMC_USER_HANDLERS] = {
{0, NULL}, {0, NULL},
{0xC3000401, smc_set_config}, {0xC3000401, smc_set_config_user},
{0xC3000002, smc_get_config}, {0xC3000002, smc_get_config_user},
{0xC3000003, smc_check_status}, {0xC3000003, smc_check_status},
{0xC3000404, smc_get_result}, {0xC3000404, smc_get_result},
{0xC3000E05, smc_exp_mod}, {0xC3000E05, smc_exp_mod},
@ -114,7 +114,7 @@ static smc_table_entry_t g_smc_priv_table[SMC_PRIV_HANDLERS] = {
{0xC4000001, smc_cpu_suspend}, {0xC4000001, smc_cpu_suspend},
{0x84000002, smc_cpu_off}, {0x84000002, smc_cpu_off},
{0xC4000003, smc_cpu_on}, {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}, {0xC3000005, smc_get_random_bytes_for_priv},
{0xC3000006, smc_panic}, {0xC3000006, smc_panic},
{0xC3000007, smc_configure_carveout}, {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; 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. */ /* 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; uint64_t out_item = 0;
uint32_t result; 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; args->X[1] = out_item;
return result; return result;
} }
@ -534,6 +534,14 @@ uint32_t smc_cpu_suspend(smc_args_t *args) {
return smc_wrapper_sync(args, cpu_suspend_wrapper); 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) { uint32_t smc_get_random_bytes_for_priv(smc_args_t *args) {
/* This is an interesting SMC. */ /* This is an interesting SMC. */
/* The kernel must NEVER be unable to get random bytes, if it needs them */ /* The kernel must NEVER be unable to get random bytes, if it needs them */

View file

@ -37,6 +37,8 @@
#define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAGS_DEFAULT 0x00000000
#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) #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 { typedef struct {
unsigned int magic; unsigned int magic;
@ -47,5 +49,7 @@ typedef struct {
#define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) #define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40))
#define EXOSPHERE_TARGETFW_KEY "target_firmware" #define EXOSPHERE_TARGETFW_KEY "target_firmware"
#define EXOSPHERE_DEBUGMODE_PRIV_KEY "debug_mode"
#define EXOSPHERE_DEBUGMODE_USER_KEY "debug_mode_user"
#endif #endif

View file

@ -53,9 +53,26 @@
static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { 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; exosphere_config_t *exo_cfg = (exosphere_config_t *)user;
int tmp = 0;
if (strcmp(section, "exosphere") == 0) { if (strcmp(section, "exosphere") == 0) {
if (strcmp(name, EXOSPHERE_TARGETFW_KEY) == 0) { if (strcmp(name, EXOSPHERE_TARGETFW_KEY) == 0) {
sscanf(value, "%d", &exo_cfg->target_firmware); 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 { } else {
return 0; return 0;
} }