From 04bbeefd7476ad930d39f20e026b8287658d06b3 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 20 Apr 2020 11:57:55 -0700 Subject: [PATCH] exo/fusee: hookup new prodinfo settings --- config_templates/BCT.ini | 10 ---- config_templates/exosphere.ini | 45 +++++++++++++++ exosphere/src/configitem.c | 10 +++- exosphere/src/configitem.h | 2 + exosphere/src/exocfg.c | 27 +++++++++ exosphere/src/exocfg.h | 5 ++ fusee/fusee-secondary/src/exocfg.h | 18 +++++- fusee/fusee-secondary/src/nxboot.c | 88 ++++++++++++++++++++++-------- 8 files changed, 171 insertions(+), 34 deletions(-) create mode 100644 config_templates/exosphere.ini diff --git a/config_templates/BCT.ini b/config_templates/BCT.ini index d83c258d9..9e23c843b 100644 --- a/config_templates/BCT.ini +++ b/config_templates/BCT.ini @@ -5,16 +5,6 @@ stage2_mtc_path = atmosphere/fusee-mtc.bin stage2_addr = 0xF0000000 stage2_entrypoint = 0xF0000000 -[exosphere] -; Note: Disabling debugmode will cause parts of ams.tma to not work, in the future. -debugmode = 1 -debugmode_user = 0 -; Note: Disabling usermode exception handlers will cause atmosphere to not fail gracefully under error conditions. -; Support will not be provided to users who disable these. If you do not know what you are doing, leave them on. -disable_user_exception_handlers = 0 -; Note: It's currently unknown what effects enabling the usermode PMU register access may have on official code. -enable_user_pmu_access = 0 - [stratosphere] ; To force-enable nogc, add nogc = 1 ; To force-disable nogc, add nogc = 0 diff --git a/config_templates/exosphere.ini b/config_templates/exosphere.ini new file mode 100644 index 000000000..dc7b3fde8 --- /dev/null +++ b/config_templates/exosphere.ini @@ -0,0 +1,45 @@ +# Key: debugmode, default: 1. +# Desc: Controls whether kernel is debug mode. +# Disabling this may break Atmosphere's debugger in a future release. + +# Key: debugmode_user, default: 0. +# Desc: Controls whether userland is debug mode. + +# Key: disable_user_exception_handlers, default: 0. +# Desc: Controls whether user exception handlers are executed on error. +# NOTE: This will cause atmosphere to not fail gracefully. +# Support may not be provided to users tho disable these. +# If you do not know what you are doing, leave them on. + +# Key: enable_user_pmu_access, default: 0. +# Desc: Controls whether userland has access to the PMU registers. +# NOTE: It is unknown what effects this has on official code. + +# Key: blank_prodinfo_sysmmc, default: 0. +# Desc: Controls whether PRODINFO should be blanked in sysmmc. +# This will cause the system to see dummied out keys and +# serial number information. +# NOTE: This is not known to be safe, as data may be +# cached elsewhere in the system. Usage is not encouraged. + +# Key: blank_prodinfo_emummc, default: 0. +# Desc: Controls whether PRODINFO should be blanked in emummc. +# NOTE: This is not known to be safe, as data may be +# cached elsewhere in the system. Usage is not encouraged. + +# Key: allow_writing_to_cal_sysmmc, default: 0. +# Desc: Controls whether PRODINFO can be written by homebrew in sysmmc. +# NOTE: Usage of this setting is strongly discouraged without +# a safe backup elsewhere. Turning this on will also cause Atmosphere +# to ensure a safe backup of calibration data is stored in unused +# mmc space, encrypted to prevent detection. This backup can be used +# to prevent unrecoverable edits in emergencies. + +[exosphere] +debugmode=1 +debugmode_user=0 +disable_user_exception_handlers=0 +enable_user_pmu_access=0 +blank_prodinfo_sysmmc=0 +blank_prodinfo_emummc=0 +allow_writing_to_cal_sysmmc=0 diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 37b8da3f7..f538ab8b3 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -290,7 +290,15 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) break; case CONFIGITEM_HAS_RCM_BUG_PATCH: /* UNOFFICIAL: Gets whether this unit has the RCM bug patched. */ - *p_outvalue = (int)(fuse_has_rcm_bug_patch());; + *p_outvalue = (int)(fuse_has_rcm_bug_patch()); + break; + case CONFIGITEM_SHOULD_BLANK_PRODINFO: + /* UNOFFICIAL: Gets whether this unit should simulate a "blanked" PRODINFO. */ + *p_outvalue = exosphere_should_blank_prodinfo(); + break; + case CONFIGITEM_ALLOW_CAL_WRITES: + /* UNOFFICIAL: Gets whether this unit should allow writing to the calibration partition. */ + *p_outvalue = exosphere_should_allow_writing_to_cal(); break; default: result = 2; diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index d460a195b..103b07c15 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -45,6 +45,8 @@ typedef enum { CONFIGITEM_NEEDS_SHUTDOWN = 65002, CONFIGITEM_EXOSPHERE_VERHASH = 65003, CONFIGITEM_HAS_RCM_BUG_PATCH = 65004, + CONFIGITEM_SHOULD_BLANK_PRODINFO = 65005, + CONFIGITEM_ALLOW_CAL_WRITES = 65006, } ConfigItem; #define REBOOT_KIND_NO_REBOOT 0 diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index dcdd1c143..7fb8c4e9d 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -27,6 +27,9 @@ static bool g_has_loaded_config = false; #define EXOSPHERE_CHECK_FLAG(flag) ((g_exosphere_cfg.flags & flag) != 0) +static unsigned int exosphere_is_emummc() { + return g_exosphere_cfg.emummc_cfg.base_cfg.magic == MAGIC_EMUMMC_CONFIG && g_exosphere_cfg.emummc_cfg.base_cfg.type != EMUMMC_TYPE_NONE; +} /* Read config out of IRAM, return target firmware version. */ unsigned int exosphere_load_config(void) { @@ -92,6 +95,30 @@ unsigned int exosphere_should_enable_usermode_pmu_access(void) { return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS); } +unsigned int exosphere_should_blank_prodinfo(void) { + if (!g_has_loaded_config) { + generic_panic(); + } + + if (exosphere_is_emummc()) { + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_BLANK_PRODINFO_EMUMMC); + } else { + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_BLANK_PRODINFO_SYSMMC); + } +} + +unsigned int exosphere_should_allow_writing_to_cal(void) { + if (!g_has_loaded_config) { + generic_panic(); + } + + if (exosphere_is_emummc()) { + return 1; + } else { + return 0; + } +} + const exo_emummc_config_t *exosphere_get_emummc_config(void) { if (!g_has_loaded_config) { generic_panic(); diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 2743dab42..7f7111898 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -41,6 +41,9 @@ #define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) #define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u) #define EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS (1 << 4u) +#define EXOSPHERE_FLAG_BLANK_PRODINFO_SYSMMC (1 << 5u) +#define EXOSPHERE_FLAG_BLANK_PRODINFO_EMUMMC (1 << 6u) +#define EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC (1 << 7u) #define EXOSPHERE_FLAGS_DEFAULT (EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV) typedef struct { @@ -60,6 +63,8 @@ unsigned int exosphere_should_override_debugmode_priv(void); unsigned int exosphere_should_override_debugmode_user(void); unsigned int exosphere_should_disable_usermode_exception_handlers(void); unsigned int exosphere_should_enable_usermode_pmu_access(void); +unsigned int exosphere_should_blank_prodinfo(void); +unsigned int exosphere_should_allow_writing_to_cal(void); const exo_emummc_config_t *exosphere_get_emummc_config(void); diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index 3b7c4644c..00b2c2ba9 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -31,6 +31,9 @@ #define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) #define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u) #define EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS (1 << 4u) +#define EXOSPHERE_FLAG_BLANK_PRODINFO_SYSMMC (1 << 5u) +#define EXOSPHERE_FLAG_BLANK_PRODINFO_EMUMMC (1 << 6u) +#define EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC (1 << 7u) #define EXOSPHERE_FLAGS_DEFAULT (EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV) typedef struct { @@ -50,5 +53,18 @@ _Static_assert(sizeof(exosphere_config_t) == 0x20 + sizeof(exo_emummc_config_t), #define EXOSPHERE_DEBUGMODE_USER_KEY "debugmode_user" #define EXOSPHERE_DISABLE_USERMODE_EXCEPTION_HANDLERS_KEY "disable_user_exception_handlers" #define EXOSPHERE_ENABLE_USERMODE_PMU_ACCESS_KEY "enable_user_pmu_access" +#define EXOSPHERE_BLANK_PRODINFO_SYSMMC_KEY "blank_prodinfo_sysmmc" +#define EXOSPHERE_BLANK_PRODINFO_EMUMMC_KEY "blank_prodinfo_emummc" +#define EXOSPHERE_ALLOW_WRITING_TO_CAL_SYSMMC_KEY "allow_writing_to_cal_sysmmc" -#endif \ No newline at end of file +typedef struct { + int debugmode; + int debugmode_user; + int disable_user_exception_handlers; + int enable_user_pmu_access; + int blank_prodinfo_sysmmc; + int blank_prodinfo_emummc; + int allow_writing_to_cal_sysmmc; +} exosphere_parse_cfg_t; + +#endif diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 35f8c77c7..d042d8c6c 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -134,38 +134,57 @@ static int emummc_ini_handler(void *user, const char *section, const char *name, } 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_parse_cfg_t *parse_cfg = (exosphere_parse_cfg_t *)user; int tmp = 0; if (strcmp(section, "exosphere") == 0) { - if (strcmp(name, EXOSPHERE_TARGETFW_KEY) == 0) { - sscanf(value, "%ld", &exo_cfg->target_firmware); - } else if (strcmp(name, EXOSPHERE_DEBUGMODE_PRIV_KEY) == 0) { + 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 (tmp == 1) { + parse_cfg->debugmode = 1; + } else if (tmp == 0) { + parse_cfg->debugmode = 0; } } else 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); + if (tmp == 1) { + parse_cfg->debugmode_user = 1; + } else if (tmp == 0) { + parse_cfg->debugmode_user = 0; } } else if (strcmp(name, EXOSPHERE_DISABLE_USERMODE_EXCEPTION_HANDLERS_KEY) == 0) { sscanf(value, "%d", &tmp); - if (tmp) { - exo_cfg->flags |= EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS; - } else { - exo_cfg->flags &= ~(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS); + if (tmp == 1) { + parse_cfg->disable_user_exception_handlers = 1; + } else if (tmp == 0) { + parse_cfg->disable_user_exception_handlers = 0; } } else if (strcmp(name, EXOSPHERE_ENABLE_USERMODE_PMU_ACCESS_KEY) == 0) { sscanf(value, "%d", &tmp); - if (tmp) { - exo_cfg->flags |= EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS; - } else { - exo_cfg->flags &= ~(EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS); + if (tmp == 1) { + parse_cfg->enable_user_pmu_access = 1; + } else if (tmp == 0) { + parse_cfg->enable_user_pmu_access = 0; + } + } else if (strcmp(name, EXOSPHERE_BLANK_PRODINFO_SYSMMC_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp == 1) { + parse_cfg->enable_user_pmu_access = 1; + } else if (tmp == 0) { + parse_cfg->enable_user_pmu_access = 0; + } + } else if (strcmp(name, EXOSPHERE_BLANK_PRODINFO_EMUMMC_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp == 1) { + parse_cfg->enable_user_pmu_access = 1; + } else if (tmp == 0) { + parse_cfg->enable_user_pmu_access = 0; + } + } else if (strcmp(name, EXOSPHERE_ALLOW_WRITING_TO_CAL_SYSMMC_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp == 1) { + parse_cfg->enable_user_pmu_access = 1; + } else if (tmp == 0) { + parse_cfg->enable_user_pmu_access = 0; } } else { return 0; @@ -354,9 +373,34 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT; } - if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) { - fatal_error("[NXBOOT] Failed to parse BCT.ini!\n"); + /* Setup exosphere parse configuration with defaults. */ + exosphere_parse_cfg_t parse_cfg = { + .debugmode = 1, + .debugmode_user = 0, + .disable_user_exception_handlers = 0, + .enable_user_pmu_access = 0, + .blank_prodinfo_sysmmc = 0, + .blank_prodinfo_emummc = 0, + .allow_writing_to_cal_sysmmc = 0, + }; + + /* If we have an ini to read, parse it. */ + char *exosphere_ini = calloc(1, 0x10000); + if (read_from_file(exosphere_ini, 0xFFFF, "exosphere.ini")) { + if (ini_parse_string(exosphere_ini, exosphere_ini_handler, &parse_cfg) < 0) { + fatal_error("[NXBOOT] Failed to parse exosphere.ini!\n"); + } } + free(exosphere_ini); + + /* Apply parse config. */ + if (parse_cfg.debugmode) exo_cfg.flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV; + if (parse_cfg.debugmode_user) exo_cfg.flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_USER; + if (parse_cfg.disable_user_exception_handlers) exo_cfg.flags |= EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS; + if (parse_cfg.enable_user_pmu_access) exo_cfg.flags |= EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS; + if (parse_cfg.blank_prodinfo_sysmmc) exo_cfg.flags |= EXOSPHERE_FLAG_BLANK_PRODINFO_SYSMMC; + if (parse_cfg.blank_prodinfo_emummc) exo_cfg.flags |= EXOSPHERE_FLAG_BLANK_PRODINFO_EMUMMC; + if (parse_cfg.allow_writing_to_cal_sysmmc) exo_cfg.flags |= EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC; if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) { fatal_error("[NXBOOT] Invalid Exosphere target firmware!\n");