exo/fusee: implement 8.0.0 support (package2 changes still TODO)

This commit is contained in:
Michael Scire 2019-04-18 01:02:12 -07:00 committed by SciresM
parent a67d4064f0
commit ae90a9d7a6
14 changed files with 107 additions and 69 deletions

View file

@ -25,11 +25,12 @@
#define ATMOSPHERE_TARGET_FIRMWARE_600 6
#define ATMOSPHERE_TARGET_FIRMWARE_620 7
#define ATMOSPHERE_TARGET_FIRMWARE_700 8
#define ATMOSPHERE_TARGET_FIRMWARE_800 9
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_700
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_800
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_700
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_800
/* TODO: What should this be, for release? */
#define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT

View file

@ -21,8 +21,8 @@
#define ATMOSPHERE_RELEASE_VERSION_MINOR 8
#define ATMOSPHERE_RELEASE_VERSION_MICRO 7
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 7
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 8
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 1
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0
#endif

View file

@ -100,6 +100,8 @@ uint64_t bootconfig_get_value_for_sysctr0(void) {
}
uint64_t bootconfig_get_memory_arrangement(void) {
/* TODO: This function has changed pretty significantly since we implemented it. */
/* Not relevant for retail, but we'll probably want this to be accurate sooner or later. */
if (bootconfig_is_debug_mode()) {
if (fuse_get_dram_id() == 4) {
if (LOADED_BOOTCONFIG->unsigned_config.data[0x23]) {

View file

@ -35,13 +35,13 @@
#undef u8
#undef u32
static bool g_battery_profile = false;
static bool g_hiz_mode_enabled = false;
static bool g_debugmode_override_user = false, g_debugmode_override_priv = false;
uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) {
switch (item) {
case CONFIGITEM_BATTERYPROFILE:
g_battery_profile = (value != 0);
case CONFIGITEM_HIZMODE:
g_hiz_mode_enabled = (value != 0);
break;
case CONFIGITEM_NEEDS_REBOOT:
/* Force a reboot, if requested. */
@ -133,8 +133,12 @@ bool configitem_is_retail(void) {
return is_retail != 0;
}
bool configitem_should_profile_battery(void) {
return g_battery_profile;
bool configitem_is_hiz_mode_enabled(void) {
return g_hiz_mode_enabled;
}
void configitem_set_hiz_mode_enabled(bool enabled) {
g_hiz_mode_enabled = enabled;
}
bool configitem_is_debugmode_priv(void) {
@ -214,8 +218,8 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
*p_outvalue = config;
}
break;
case CONFIGITEM_BATTERYPROFILE:
*p_outvalue = (int)g_battery_profile;
case CONFIGITEM_HIZMODE:
*p_outvalue = (int)g_hiz_mode_enabled;
break;
case CONFIGITEM_ISQUESTUNIT:
/* Added on 3.0, used to determine whether console is a kiosk unit. */

View file

@ -33,7 +33,7 @@ typedef enum {
CONFIGITEM_MEMORYARRANGE = 10,
CONFIGITEM_ISDEBUGMODE = 11,
CONFIGITEM_KERNELCONFIGURATION = 12,
CONFIGITEM_BATTERYPROFILE = 13,
CONFIGITEM_HIZMODE = 13,
CONFIGITEM_ISQUESTUNIT = 14,
CONFIGITEM_NEWHARDWARETYPE_5X = 15,
CONFIGITEM_NEWKEYGENERATION_5X = 16,
@ -56,10 +56,11 @@ 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);
bool configitem_is_hiz_mode_enabled(void);
bool configitem_is_debugmode_priv(void);
void configitem_set_debugmode_override(bool user, bool priv);
void configitem_set_hiz_mode_enabled(bool enabled);
uint64_t configitem_get_hardware_type(void);

View file

@ -140,13 +140,19 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6
carveout->size_big_pages = (uint32_t)(size >> 17);
carveout->client_access_0 = (BIT(CSR_PTCR) | BIT(CSR_DISPLAY0A) | BIT(CSR_DISPLAY0AB) | BIT(CSR_DISPLAY0B) | BIT(CSR_DISPLAY0BB) | BIT(CSR_DISPLAY0C) | BIT(CSR_DISPLAY0CB) | BIT(CSR_AFIR) | BIT(CSR_DISPLAYHC) | BIT(CSR_DISPLAYHCB) | BIT(CSR_HDAR) | BIT(CSR_HOST1XDMAR) | BIT(CSR_HOST1XR) | BIT(CSR_NVENCSRD) | BIT(CSR_PPCSAHBDMAR) | BIT(CSR_PPCSAHBSLVR));
carveout->client_access_1 = (BIT(CSR_MPCORER) | BIT(CSW_NVENCSWR) | BIT(CSW_AFIW) | BIT(CSW_HDAW) | BIT(CSW_HOST1XW) | BIT(CSW_MPCOREW) | BIT(CSW_PPCSAHBDMAW) | BIT(CSW_PPCSAHBSLVW));
carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW) | BIT(CSR_TSECSRD) | BIT(CSW_TSECSWR));
carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR));
carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR));
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_800) {
carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW));
carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR));
carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR) | BIT(CSR_TSECSRDB) | BIT(CSW_TSECSWRB));
} else {
carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW) | BIT(CSR_TSECSRD) | BIT(CSW_TSECSWR));
carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR));
carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR));
}
carveout->client_force_internal_access_0 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSR_AVPCARM7R) : 0;
carveout->client_force_internal_access_1 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0;
carveout->client_force_internal_access_2 = 0;
carveout->client_force_internal_access_3 = 0;
carveout->client_force_internal_access_4 = 0;
carveout->config = 0x8B;
carveout->config = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_800) ? 0x4CB : 0x8B;
}

View file

@ -144,6 +144,7 @@ static void setup_se(void) {
master_kek_source_ind = MASTERKEY_REVISION_620 - MASTERKEY_REVISION_620;
break;
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
master_kek_source_ind = MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_620;
break;
default:
@ -179,6 +180,7 @@ static void setup_se(void) {
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY);
break;
}
@ -487,6 +489,7 @@ static void copy_warmboot_bin_to_dram() {
warmboot_src = (uint8_t *)0x4003D800;
break;
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
warmboot_src = (uint8_t *)0x4003E000;
break;
}
@ -554,6 +557,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
MAKE_REG32(PMC_BASE + 0x360) = 0xA8;
break;
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
MAKE_REG32(PMC_BASE + 0x360) = 0x129;
break;
}

View file

@ -44,11 +44,11 @@
#undef u8
#undef u32
static void configure_battery_hi_z_mode(void) {
static void configure_battery_hiz_mode(void) {
clkrst_reboot(CARDEVICE_I2C1);
if (configitem_should_profile_battery() && !i2c_query_ti_charger_bit_7()) {
/* Profile the battery. */
if (configitem_is_hiz_mode_enabled() && !i2c_query_ti_charger_bit_7()) {
/* Configure HiZ mode. */
i2c_set_ti_charger_bit_7();
uint32_t start_time = get_time();
bool should_wait = true;
@ -109,7 +109,7 @@ static void mitigate_jamais_vu(void) {
}
/* Jamais Vu mitigation #3: Ensure all relevant DMA controllers are held in reset. */
if ((CLK_RST_CONTROLLER_RST_DEVICES_H_0 & 0x4000004) != 0x4000004) {
if ((CLK_RST_CONTROLLER_RST_DEVICES_H_0 & 0x4000006) != 0x4000006) {
generic_panic();
}
}
@ -262,7 +262,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen
}
/* Perform I2C comms with TI charger if required. */
configure_battery_hi_z_mode();
configure_battery_hiz_mode();
/* Enable LP0 Wake Event Detection. */
enable_lp0_wake_events();

View file

@ -83,8 +83,12 @@ uint32_t smc_read_write_register(smc_args_t *args);
/* Atmosphere SMC prototypes */
uint32_t smc_ams_iram_copy(smc_args_t *args);
/* TODO: Provide a way to set this. It's 0 on non-recovery boot anyway... */
static uint32_t g_smc_blacklist_mask = 0;
typedef struct {
uint32_t id;
uint32_t blacklist_mask;
uint32_t (*handler)(smc_args_t *args);
} smc_table_entry_t;
@ -94,43 +98,43 @@ typedef struct {
} smc_table_t;
static smc_table_entry_t g_smc_user_table[SMC_USER_HANDLERS] = {
{0, NULL},
{0xC3000401, smc_set_config_user},
{0xC3000002, smc_get_config_user},
{0xC3000003, smc_check_status},
{0xC3000404, smc_get_result},
{0xC3000E05, smc_exp_mod},
{0xC3000006, smc_get_random_bytes_for_user},
{0xC3000007, smc_generate_aes_kek},
{0xC3000008, smc_load_aes_key},
{0xC3000009, smc_crypt_aes},
{0xC300000A, smc_generate_specific_aes_key},
{0xC300040B, smc_compute_cmac},
{0xC300100C, smc_load_rsa_oaep_key},
{0xC300100D, smc_decrypt_rsa_private_key},
{0xC300100E, smc_load_secure_exp_mod_key},
{0xC300060F, smc_secure_exp_mod},
{0xC3000610, smc_unwrap_rsa_oaep_wrapped_titlekey},
{0xC3000011, smc_load_titlekey},
{0xC3000012, smc_unwrap_aes_wrapped_titlekey}
{0, 4, NULL},
{0xC3000401, 4, smc_set_config_user},
{0xC3000002, 1, smc_get_config_user},
{0xC3000003, 1, smc_check_status},
{0xC3000404, 1, smc_get_result},
{0xC3000E05, 4, smc_exp_mod},
{0xC3000006, 1, smc_get_random_bytes_for_user},
{0xC3000007, 1, smc_generate_aes_kek},
{0xC3000008, 1, smc_load_aes_key},
{0xC3000009, 1, smc_crypt_aes},
{0xC300000A, 1, smc_generate_specific_aes_key},
{0xC300040B, 1, smc_compute_cmac},
{0xC300100C, 1, smc_load_rsa_oaep_key},
{0xC300100D, 2, smc_decrypt_rsa_private_key},
{0xC300100E, 4, smc_load_secure_exp_mod_key},
{0xC300060F, 2, smc_secure_exp_mod},
{0xC3000610, 4, smc_unwrap_rsa_oaep_wrapped_titlekey},
{0xC3000011, 4, smc_load_titlekey},
{0xC3000012, 4, smc_unwrap_aes_wrapped_titlekey}
};
static smc_table_entry_t g_smc_priv_table[SMC_PRIV_HANDLERS] = {
{0, NULL},
{0xC4000001, smc_cpu_suspend},
{0x84000002, smc_cpu_off},
{0xC4000003, smc_cpu_on},
{0xC3000004, smc_get_config_priv},
{0xC3000005, smc_get_random_bytes_for_priv},
{0xC3000006, smc_panic},
{0xC3000007, smc_configure_carveout},
{0xC3000008, smc_read_write_register}
{0, 4, NULL},
{0xC4000001, 4, smc_cpu_suspend},
{0x84000002, 4, smc_cpu_off},
{0xC4000003, 1, smc_cpu_on},
{0xC3000004, 1, smc_get_config_priv},
{0xC3000005, 1, smc_get_random_bytes_for_priv},
{0xC3000006, 1, smc_panic},
{0xC3000007, 1, smc_configure_carveout},
{0xC3000008, 1, smc_read_write_register}
};
/* This is a table used for atmosphere-specific SMCs. */
static smc_table_entry_t g_smc_ams_table[SMC_AMS_HANDLERS] = {
{0, NULL},
{0xF0000201, smc_ams_iram_copy},
{0, 4, NULL},
{0xF0000201, 0, smc_ams_iram_copy},
};
static smc_table_t g_smc_tables[SMC_HANDLER_COUNT + 1] = {
@ -177,6 +181,7 @@ void set_version_specific_smcs(void) {
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
/* No more LoadSecureExpModKey. */
g_smc_user_table[0xE].handler = NULL;
g_smc_user_table[0xC].id = 0xC300D60C;
@ -292,13 +297,17 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) {
#endif
/* Call function. */
args->X[0] = smc_handler(args);
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_800 ||
(g_smc_tables[handler_id].handlers[smc_id].blacklist_mask & g_smc_blacklist_mask) == 0) {
args->X[0] = smc_handler(args);
} else {
/* Call not allowed due to current boot conditions. */
args->X[0] = 6;
}
#if DEBUG_LOG_SMCS
if (handler_id == SMC_HANDLER_USER) {
*(volatile smc_args_t *)(get_iram_address_for_debug() + 0x100 + ((0x80 * num + 0x40) & 0x3FFF)) = *args;
/*if (num >= 0x69) {
panic(PANIC_REBOOT);
}*/
}
#endif

View file

@ -51,6 +51,7 @@ static bool is_user_keyslot_valid(unsigned int keyslot) {
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
default:
return keyslot <= 5;
}

View file

@ -67,8 +67,8 @@ void init_dma_controllers(unsigned int target_firmware) {
/* MSELECT_CONFIG_0 |= WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */
MAKE_REG32(0x50060000) |= 0x38000000;
/* AHB_ARBITRATION_DISABLE_0 - Disables USB and USB2 from arbitration */
MAKE_REG32(0x6000C004) = 0x40040;
/* AHB_ARBITRATION_DISABLE_0 - Disables USB, USB2, and AHB-DMA from arbitration */
MAKE_REG32(0x6000C004) = 0x40060;
/* AHB_ARBITRATION_PRIORITY_CTRL_0 - Select high prio group with prio 7 */
MAKE_REG32(0x6000C008) = 0xE0000001;

View file

@ -39,6 +39,17 @@ uintptr_t get_warmboot_main_stack_address(void) {
return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x780;
}
static void warmboot_configure_hiz_mode(void) {
/* Enable input to I2C1 */
PINMUX_AUX_GEN1_I2C_SCL_0 = 0x40;
PINMUX_AUX_GEN1_I2C_SDA_0 = 0x40;
clkrst_reboot(CARDEVICE_I2C1);
i2c_init(0);
i2c_clear_ti_charger_bit_7();
clkrst_disable(CARDEVICE_I2C1);
}
void __attribute__((noreturn)) warmboot_main(void) {
/*
This function and its callers are reached in either of the following events, under normal conditions:
@ -79,15 +90,10 @@ void __attribute__((noreturn)) warmboot_main(void) {
/* Make PMC (2.x+), MC (4.x+) registers secure-only */
secure_additional_devices();
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400 || configitem_get_hardware_type() == 0) {
/* Enable input to I2C1 */
PINMUX_AUX_GEN1_I2C_SCL_0 = 0x40;
PINMUX_AUX_GEN1_I2C_SDA_0 = 0x40;
clkrst_reboot(CARDEVICE_I2C1);
i2c_init(0);
i2c_clear_ti_charger_bit_7();
clkrst_disable(CARDEVICE_I2C1);
if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) ||
((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_800) && configitem_get_hardware_type() == 0) ||
(configitem_is_hiz_mode_enabled())) {
warmboot_configure_hiz_mode();
}
clear_user_smc_in_progress();

View file

@ -149,6 +149,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
desired_keyblob = MASTERKEY_REVISION_620;
break;
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
desired_keyblob = MASTERKEY_REVISION_700_CURRENT;
break;
default:
@ -223,6 +224,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10);

View file

@ -170,8 +170,10 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
fatal_error("[NXBOOT]: Unable to identify package1!\n");
}
}
case 0x0F:
case 0x0F: /* 7.0.0 - 7.0.1 */
return ATMOSPHERE_TARGET_FIRMWARE_700;
case 0x10: /* 8.0.0 */
return ATMOSPHERE_TARGET_FIRMWARE_800;
default:
fatal_error("[NXBOOT]: Unable to identify package1!\n");
}
@ -412,7 +414,7 @@ uint32_t nxboot_main(void) {
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n");
}
if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) {
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) {
tsec_fw_size = 0x3000;
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
tsec_fw_size = 0x2900;