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"
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:
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();

View file

@ -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

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

View file

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

View file

@ -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 */

View file

@ -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

View file

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