ams: revamp target firmware

This commit is contained in:
Michael Scire 2020-05-06 22:29:07 -07:00
parent 85cd2c97a0
commit 8e75a4169d
48 changed files with 863 additions and 693 deletions

View file

@ -43,7 +43,7 @@ void lp0_entry_main(warmboot_metadata_t *meta) {
} }
/* [4.0.0+] First thing warmboot does is disable BPMP access to memory. */ /* [4.0.0+] First thing warmboot does is disable BPMP access to memory. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
disable_bpmp_access_to_dram(); disable_bpmp_access_to_dram();
} }
@ -56,7 +56,7 @@ void lp0_entry_main(warmboot_metadata_t *meta) {
reboot(); reboot();
} }
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_300) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
/* Nintendo's firmware checks APBDEV_PMC_SECURE_SCRATCH32_0 against a per-warmboot binary value here. */ /* Nintendo's firmware checks APBDEV_PMC_SECURE_SCRATCH32_0 against a per-warmboot binary value here. */
/* We won't bother with that. */ /* We won't bother with that. */
if (false /* APBDEV_PMC_SECURE_SCRATCH32_0 == WARMBOOT_MAGIC_NUMBER */) { if (false /* APBDEV_PMC_SECURE_SCRATCH32_0 == WARMBOOT_MAGIC_NUMBER */) {
@ -90,7 +90,7 @@ void lp0_entry_main(warmboot_metadata_t *meta) {
/* Nintendo clears most of warmboot.bin out of IRAM here. We're not gonna bother. */ /* Nintendo clears most of warmboot.bin out of IRAM here. We're not gonna bother. */
/* memset( ... ); */ /* memset( ... ); */
const uint32_t halt_val = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x40000000 : 0x50000000; const uint32_t halt_val = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ? 0x40000000 : 0x50000000;
while (true) { while (true) {
/* Halt the BPMP. */ /* Halt the BPMP. */
FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val; FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val;

View file

@ -30,13 +30,13 @@ static void secmon_decrypt_saved_image(void *dst, const void *src, size_t size);
void secmon_restore_to_tzram(const uint32_t target_firmware) { void secmon_restore_to_tzram(const uint32_t target_firmware) {
/* Newer warmboot binaries clear the untouched keyslots for safety. */ /* Newer warmboot binaries clear the untouched keyslots for safety. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
secmon_clear_unused_keyslots(); secmon_clear_unused_keyslots();
} }
/* Decrypt Secure Monitor from DRAM into TZRAM. */ /* Decrypt Secure Monitor from DRAM into TZRAM. */
void *tzram_src = (void *)(0x80010000); void *tzram_src = (void *)(0x80010000);
void *tzram_dst = (void *)(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500 ? 0x7C012000 : 0x7C010000); void *tzram_dst = (void *)(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ? 0x7C012000 : 0x7C010000);
const size_t tzram_size = 0xE000; const size_t tzram_size = 0xE000;
secmon_decrypt_saved_image(tzram_dst, tzram_src, tzram_size); secmon_decrypt_saved_image(tzram_dst, tzram_src, tzram_size);

View file

@ -52,7 +52,7 @@ void setup_dram_magic_numbers(void) {
unsigned int target_fw = exosphere_get_target_firmware(); unsigned int target_fw = exosphere_get_target_firmware();
(*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; /* Access test value. */ (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; /* Access test value. */
flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000);
if (ATMOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { if (ATMOSPHERE_TARGET_FIRMWARE_6_0_0 <= target_fw) {
(*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; /* SKU code. */ (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; /* SKU code. */
(*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002;
(*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; /* Tegra210 code. */ (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; /* Tegra210 code. */
@ -81,7 +81,7 @@ void bootup_misc_mmio(void) {
se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY); se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY);
se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY); se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY);
if (!g_has_booted_up && (ATMOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware())) { if (!g_has_booted_up && (ATMOSPHERE_TARGET_FIRMWARE_6_0_0 > exosphere_get_target_firmware())) {
setup_dram_magic_numbers(); setup_dram_magic_numbers();
} }
@ -116,7 +116,7 @@ void bootup_misc_mmio(void) {
configure_default_carveouts(); configure_default_carveouts();
/* Mark registers secure world only. */ /* Mark registers secure world only. */
if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_100) { if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_1_0_0) {
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SATA | APB_SSER0_LA; APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SATA | APB_SSER0_LA;
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 = APB_SSER1_SPI1 | APB_SSER1_SPI2 | APB_SSER1_SPI3 | APB_SSER1_SPI5 | APB_SSER1_SPI6 | APB_SSER1_I2C4 | APB_SSER1_I2C6; APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 = APB_SSER1_SPI1 | APB_SSER1_SPI2 | APB_SSER1_SPI3 | APB_SSER1_SPI5 | APB_SSER1_SPI6 | APB_SSER1_I2C4 | APB_SSER1_I2C6;
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = 1 << 4 | 1 << 5 | APB_SSER2_DDS; /* bits 4 and 5 are not labeled in 21.1.7.3 */ APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = 1 << 4 | 1 << 5 | APB_SSER2_DDS; /* bits 4 and 5 are not labeled in 21.1.7.3 */
@ -133,7 +133,7 @@ void bootup_misc_mmio(void) {
/* Also mark I2C4 secure only, */ /* Also mark I2C4 secure only, */
sec_disable_1 |= APB_SSER1_I2C4; sec_disable_1 |= APB_SSER1_I2C4;
} }
if (hardware_type != 0 && exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (hardware_type != 0 && exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
/* Starting on 4.x on non-dev units, mark UARTB, UARTC, SPI4, I2C3 secure only. */ /* Starting on 4.x on non-dev units, mark UARTB, UARTC, SPI4, I2C3 secure only. */
sec_disable_1 |= APB_SSER1_UART_B | APB_SSER1_UART_C | APB_SSER1_SPI4 | APB_SSER1_I2C3; sec_disable_1 |= APB_SSER1_UART_B | APB_SSER1_UART_C | APB_SSER1_SPI4 | APB_SSER1_I2C3;
/* Starting on 4.x on non-dev units, mark SDMMC1 secure only. */ /* Starting on 4.x on non-dev units, mark SDMMC1 secure only. */
@ -151,7 +151,7 @@ void bootup_misc_mmio(void) {
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF; MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF;
/* Set SMMU ASID security registers. */ /* Set SMMU ASID security registers. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0xE; MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0xE;
} else { } else {
MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0x0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0x0;
@ -164,7 +164,7 @@ void bootup_misc_mmio(void) {
MAKE_MC_REG(MC_SMMU_ASID_SECURITY_6) = 0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY_6) = 0;
MAKE_MC_REG(MC_SMMU_ASID_SECURITY_7) = 0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY_7) = 0;
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0; MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0;
} }
MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0; MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0;
@ -180,7 +180,7 @@ void bootup_misc_mmio(void) {
/* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */ /* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */
uint32_t reset_vec; uint32_t reset_vec;
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
reset_vec = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); reset_vec = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN);
} else { } else {
reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN);
@ -206,7 +206,7 @@ void bootup_misc_mmio(void) {
intr_set_cpu_mask(INTERRUPT_ID_SECURITY_ENGINE, 8); intr_set_cpu_mask(INTERRUPT_ID_SECURITY_ENGINE, 8);
intr_set_edge_level(INTERRUPT_ID_SECURITY_ENGINE, 0); intr_set_edge_level(INTERRUPT_ID_SECURITY_ENGINE, 0);
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
intr_set_priority(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); intr_set_priority(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0);
intr_set_group(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); intr_set_group(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0);
intr_set_enabled(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 1); intr_set_enabled(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 1);
@ -221,14 +221,14 @@ void bootup_misc_mmio(void) {
uart_init(UART_A, 115200); uart_init(UART_A, 115200);
intr_register_handler(INTERRUPT_ID_SECURITY_ENGINE, se_operation_completed); intr_register_handler(INTERRUPT_ID_SECURITY_ENGINE, se_operation_completed);
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
intr_register_handler(INTERRUPT_ID_ACTIVITY_MONITOR_4X, actmon_interrupt_handler); intr_register_handler(INTERRUPT_ID_ACTIVITY_MONITOR_4X, actmon_interrupt_handler);
} }
for (unsigned int core = 1; core < NUM_CPU_CORES; core++) { for (unsigned int core = 1; core < NUM_CPU_CORES; core++) {
set_core_is_active(core, false); set_core_is_active(core, false);
} }
g_has_booted_up = true; g_has_booted_up = true;
} else if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) { } else if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
/* Disable AHB redirect. */ /* Disable AHB redirect. */
MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000;
MAKE_MC_REG(MC_IRAM_TOM) = 0; MAKE_MC_REG(MC_IRAM_TOM) = 0;
@ -238,7 +238,7 @@ void bootup_misc_mmio(void) {
} }
void setup_4x_mmio(void) { void setup_4x_mmio(void) {
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
configure_gpu_ucode_carveout(); configure_gpu_ucode_carveout();
} }
@ -361,9 +361,9 @@ void identity_unmap_iram_cd_tzram(void) {
} }
void secure_additional_devices(void) { void secure_additional_devices(void) {
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 |= APB_SSER0_PMC; /* make PMC secure-only (2.x+) */ APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 |= APB_SSER0_PMC; /* make PMC secure-only (2.x+) */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 |= APB_SSER1_MC0 | APB_SSER1_MC1 | APB_SSER1_MCB; /* make MC0, MC1, MCB secure-only (4.x+) */ APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 |= APB_SSER1_MC0 | APB_SSER1_MC1 | APB_SSER1_MCB; /* make MC0, MC1, MCB secure-only (4.x+) */
} }
} }

View file

@ -26,7 +26,7 @@
#undef MAILBOX_NX_BOOTLOADER_BASE #undef MAILBOX_NX_BOOTLOADER_BASE
#undef TIMERS_BASE #undef TIMERS_BASE
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MMIO_GET_DEVICE_7X_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) : (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) #define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? (MMIO_GET_DEVICE_7X_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) : (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
#define TIMERS_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_TMRs_WDTs)) #define TIMERS_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_TMRs_WDTs))
extern const uint8_t __start_cold[]; extern const uint8_t __start_cold[];
@ -56,7 +56,7 @@ static void mmio_map_all_devices(uintptr_t *mmu_l3_tbl, unsigned int target_firm
static const uintptr_t pas_7x[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV7X, COMMA) }; static const uintptr_t pas_7x[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV7X, COMMA) };
for(size_t i = 0, offset = 0; i < MMIO_DEVID_MAX; i++) { for(size_t i = 0, offset = 0; i < MMIO_DEVID_MAX; i++) {
uintptr_t pa = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) ? pas[i] : pas_7x[i]; uintptr_t pa = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? pas[i] : pas_7x[i];
mmio_map_device(mmu_l3_tbl, MMIO_BASE + offset, pa, sizes[i], is_secure[i]); mmio_map_device(mmu_l3_tbl, MMIO_BASE + offset, pa, sizes[i], is_secure[i]);
offset += sizes[i]; offset += sizes[i];
offset += 0x1000; offset += 0x1000;
@ -94,7 +94,7 @@ static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl, unsigned int target_fi
static const uintptr_t offs_5x[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZ5XS, COMMA) }; static const uintptr_t offs_5x[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZ5XS, COMMA) };
for(size_t i = 0, offset = 0; i < TZRAM_SEGMENT_ID_MAX; i++) { for(size_t i = 0, offset = 0; i < TZRAM_SEGMENT_ID_MAX; i++) {
uintptr_t off = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_500) ? offs[i] : offs_5x[i]; uintptr_t off = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) ? offs[i] : offs_5x[i];
tzram_map_segment(mmu_l3_tbl, TZRAM_SEGMENT_BASE + offset, 0x7C010000ull + off, sizes[i], is_executable[i]); tzram_map_segment(mmu_l3_tbl, TZRAM_SEGMENT_BASE + offset, 0x7C010000ull + off, sizes[i], is_executable[i]);
offset += increments[i]; offset += increments[i];
} }
@ -104,7 +104,7 @@ static void configure_ttbls(unsigned int target_firmware) {
uintptr_t *mmu_l1_tbl; uintptr_t *mmu_l1_tbl;
uintptr_t *mmu_l2_tbl; uintptr_t *mmu_l2_tbl;
uintptr_t *mmu_l3_tbl; uintptr_t *mmu_l3_tbl;
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_500) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64);
mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE);
mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
@ -154,7 +154,7 @@ uintptr_t get_coldboot_crt0_temp_stack_address(void) {
} }
uintptr_t get_coldboot_crt0_stack_address(void) { uintptr_t get_coldboot_crt0_stack_address(void) {
if (exosphere_get_target_firmware_for_init() < ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware_for_init() < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800;
} else { } else {
return TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; return TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800;
@ -196,7 +196,7 @@ void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold)
init_dma_controllers(g_exosphere_target_firmware_for_init); init_dma_controllers(g_exosphere_target_firmware_for_init);
configure_ttbls(g_exosphere_target_firmware_for_init); configure_ttbls(g_exosphere_target_firmware_for_init);
if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) { if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
set_memory_registers_enable_mmu_1x_ttbr0(); set_memory_registers_enable_mmu_1x_ttbr0();
} else { } else {
set_memory_registers_enable_mmu_5x_ttbr0(); set_memory_registers_enable_mmu_5x_ttbr0();

View file

@ -203,7 +203,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
break; break;
case CONFIGITEM_BOOTREASON: case CONFIGITEM_BOOTREASON:
/* For some reason, Nintendo removed it on 4.0 */ /* For some reason, Nintendo removed it on 4.0 */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
*p_outvalue = bootconfig_get_boot_reason(); *p_outvalue = bootconfig_get_boot_reason();
} else { } else {
result = 2; result = 2;
@ -238,7 +238,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
break; break;
case CONFIGITEM_ISQUESTUNIT: case CONFIGITEM_ISQUESTUNIT:
/* Added on 3.0, used to determine whether console is a kiosk unit. */ /* Added on 3.0, used to determine whether console is a kiosk unit. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_300) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
*p_outvalue = (fuse_get_reserved_odm(4) >> 10) & 1; *p_outvalue = (fuse_get_reserved_odm(4) >> 10) & 1;
} else { } else {
result = 2; result = 2;
@ -246,7 +246,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
break; break;
case CONFIGITEM_NEWHARDWARETYPE_5X: case CONFIGITEM_NEWHARDWARETYPE_5X:
/* Added in 5.x, currently hardcoded to 0. */ /* Added in 5.x, currently hardcoded to 0. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
*p_outvalue = 0; *p_outvalue = 0;
} else { } else {
result = 2; result = 2;
@ -254,7 +254,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
break; break;
case CONFIGITEM_NEWKEYGENERATION_5X: case CONFIGITEM_NEWKEYGENERATION_5X:
/* Added in 5.x. */ /* Added in 5.x. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
*p_outvalue = fuse_get_5x_key_generation(); *p_outvalue = fuse_get_5x_key_generation();
} else { } else {
result = 2; result = 2;
@ -262,7 +262,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
break; break;
case CONFIGITEM_PACKAGE2HASH_5X: case CONFIGITEM_PACKAGE2HASH_5X:
/* Added in 5.x. */ /* Added in 5.x. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500 && bootconfig_is_recovery_boot()) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0 && bootconfig_is_recovery_boot()) {
bootconfig_get_package2_hash_for_recovery(p_outvalue); bootconfig_get_package2_hash_for_recovery(p_outvalue);
} else { } else {
result = 2; result = 2;
@ -270,11 +270,11 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
break; break;
case CONFIGITEM_EXOSPHERE_VERSION: case CONFIGITEM_EXOSPHERE_VERSION:
/* UNOFFICIAL: Gets information about the current exosphere version. */ /* UNOFFICIAL: Gets information about the current exosphere version. */
*p_outvalue = ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MAJOR & 0xFF) << 32ull) | *p_outvalue = ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MAJOR & 0xFF) << 56ull) |
((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MINOR & 0xFF) << 24ull) | ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MINOR & 0xFF) << 48ull) |
((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MICRO & 0xFF) << 16ull) | ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MICRO & 0xFF) << 40ull) |
((uint64_t)(exosphere_get_target_firmware() & 0xFF) << 8ull) | ((uint64_t)(mkey_get_revision() & 0xFF) << 32ull) |
((uint64_t)(mkey_get_revision() & 0xFF) << 0ull); ((uint64_t)(exosphere_get_target_firmware()) << 0ull);
break; break;
case CONFIGITEM_NEEDS_REBOOT: case CONFIGITEM_NEEDS_REBOOT:
/* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting. */ /* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting. */

View file

@ -100,7 +100,7 @@ uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) {
static const uint32_t status_masks[NUM_CPU_CORES] = {0x4000, 0x200, 0x400, 0x800}; static const uint32_t status_masks[NUM_CPU_CORES] = {0x4000, 0x200, 0x400, 0x800};
static const uint32_t toggle_vals[NUM_CPU_CORES] = {0xE, 0x9, 0xA, 0xB}; static const uint32_t toggle_vals[NUM_CPU_CORES] = {0xE, 0x9, 0xA, 0xB};
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
/* Reset the core */ /* Reset the core */
CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 = (1 << (core + 0x10)) | (1 << core); CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 = (1 << (core + 0x10)) | (1 << core);
} }
@ -133,7 +133,7 @@ uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) {
} }
CPU_ON_SUCCESS: CPU_ON_SUCCESS:
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
/* Start the core */ /* Start the core */
CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = (1 << (core + 0x10)) | (1 << core); CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = (1 << (core + 0x10)) | (1 << core);
} }

View file

@ -196,7 +196,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1)); uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
/* Firmware from versions 1.0.0 to 3.0.2. */ /* Firmware from versions 1.0.0 to 3.0.2. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
if (hardware_type >= 1) { if (hardware_type >= 1) {
return (hardware_type > 2) ? 3 : hardware_type - 1; return (hardware_type > 2) ? 3 : hardware_type - 1;
@ -205,7 +205,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
} else { } else {
return 3; return 3;
} }
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */ } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* Firmware versions from 4.0.0 to 6.2.0. */
static const uint32_t types[] = {0,1,4,3}; static const uint32_t types[] = {0,1,4,3};
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C); hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
hardware_type--; hardware_type--;
@ -262,30 +262,39 @@ uint32_t fuse_get_5x_key_generation(void) {
/* Returns the fuse version expected for the firmware. */ /* Returns the fuse version expected for the firmware. */
uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware) { uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware) {
static const uint8_t expected_versions[ATMOSPHERE_TARGET_FIRMWARE_COUNT+1] = { if (fuse_get_retail_type() != 0) {
[ATMOSPHERE_TARGET_FIRMWARE_100] = 1, if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
[ATMOSPHERE_TARGET_FIRMWARE_200] = 2, return 13;
[ATMOSPHERE_TARGET_FIRMWARE_300] = 3, } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_1_0) {
/* [ATMOSPHERE_TARGET_FIRMWARE_302] = 4, */ return 12;
[ATMOSPHERE_TARGET_FIRMWARE_400] = 5, } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0) {
[ATMOSPHERE_TARGET_FIRMWARE_500] = 6, return 11;
[ATMOSPHERE_TARGET_FIRMWARE_600] = 7, } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
[ATMOSPHERE_TARGET_FIRMWARE_620] = 8, return 10;
[ATMOSPHERE_TARGET_FIRMWARE_700] = 9, } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
[ATMOSPHERE_TARGET_FIRMWARE_800] = 9, return 9;
[ATMOSPHERE_TARGET_FIRMWARE_810] = 10, } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
[ATMOSPHERE_TARGET_FIRMWARE_900] = 11, return 8;
[ATMOSPHERE_TARGET_FIRMWARE_910] = 12, } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
[ATMOSPHERE_TARGET_FIRMWARE_1000] = 13, return 7;
}; } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
return 6;
if (target_firmware > ATMOSPHERE_TARGET_FIRMWARE_COUNT) { } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
generic_panic(); return 5;
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_2) {
return 4;
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
return 3;
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
return 2;
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_1_0_0) {
return 1;
} else {
return 0;
}
} else {
return (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) ? 1 : 0;
} }
if (fuse_get_retail_type() != 0)
return expected_versions[target_firmware];
else
return (target_firmware > ATMOSPHERE_TARGET_FIRMWARE_200) ? 1 : 0;
} }
/* Check for RCM bug patches. */ /* Check for RCM bug patches. */

View file

@ -47,7 +47,7 @@ void configure_gpu_ucode_carveout(void) {
carveout->size_big_pages = 2; /* 0x40000 */ carveout->size_big_pages = 2; /* 0x40000 */
carveout->client_access_0 = 0; carveout->client_access_0 = 0;
carveout->client_access_1 = 0; carveout->client_access_1 = 0;
carveout->client_access_2 = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); carveout->client_access_2 = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR));
carveout->client_access_3 = 0; carveout->client_access_3 = 0;
carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2));
carveout->client_force_internal_access_0 = 0; carveout->client_force_internal_access_0 = 0;
@ -77,7 +77,7 @@ void configure_default_carveouts(void) {
carveout->config = 0x4000006; carveout->config = 0x4000006;
/* Configure Carveout 2 (GPU UCODE) */ /* Configure Carveout 2 (GPU UCODE) */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_600) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
configure_gpu_ucode_carveout(); configure_gpu_ucode_carveout();
} }
@ -99,7 +99,7 @@ void configure_default_carveouts(void) {
carveout->config = 0x4401E7E; carveout->config = 0x4401E7E;
/* Configure default Kernel carveouts based on 2.0.0+. */ /* Configure default Kernel carveouts based on 2.0.0+. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
/* Configure Carveout 4 (KERNEL_BUILTINS) */ /* Configure Carveout 4 (KERNEL_BUILTINS) */
configure_kernel_carveout(4, g_saved_carveouts[0].address, g_saved_carveouts[0].size); configure_kernel_carveout(4, g_saved_carveouts[0].address, g_saved_carveouts[0].size);
@ -140,11 +140,11 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6
carveout->size_big_pages = (uint32_t)(size >> 17); 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_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_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));
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_810) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW)); 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_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); 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_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR));
carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR)); carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR));
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_800) { } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW)); 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_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)); carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR) | BIT(CSR_TSECSRDB) | BIT(CSW_TSECSWRB));
@ -153,10 +153,10 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6
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_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_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_0 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) && (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_1 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0;
carveout->client_force_internal_access_2 = 0; carveout->client_force_internal_access_2 = 0;
carveout->client_force_internal_access_3 = 0; carveout->client_force_internal_access_3 = 0;
carveout->client_force_internal_access_4 = 0; carveout->client_force_internal_access_4 = 0;
carveout->config = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_800) ? 0x4CB : 0x8B; carveout->config = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0) ? 0x4CB : 0x8B;
} }

View file

@ -82,7 +82,7 @@ static void derive_new_device_keys(unsigned int keygen_keyslot) {
break; break;
} else if (relative_revision == mkey_get_revision()) { } else if (relative_revision == mkey_get_revision()) {
/* On 7.0.0, sept will have derived this key for us already. */ /* On 7.0.0, sept will have derived this key for us already. */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_700) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
decrypt_data_into_keyslot(KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10);
} }
} else { } else {
@ -133,25 +133,15 @@ static void setup_se(void) {
mkey_detect_revision(); mkey_detect_revision();
/* Derive new device keys. */ /* Derive new device keys. */
switch (exosphere_get_target_firmware()) { {
case ATMOSPHERE_TARGET_FIRMWARE_100: const uint32_t target_fw = exosphere_get_target_firmware();
case ATMOSPHERE_TARGET_FIRMWARE_200: if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
case ATMOSPHERE_TARGET_FIRMWARE_300:
break;
case ATMOSPHERE_TARGET_FIRMWARE_400:
derive_new_device_keys(KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY);
break;
case ATMOSPHERE_TARGET_FIRMWARE_500:
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
case ATMOSPHERE_TARGET_FIRMWARE_910:
case ATMOSPHERE_TARGET_FIRMWARE_1000:
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY);
break; } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
derive_new_device_keys(KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY);
} else {
/* No new keys to derive */
}
} }
se_initialize_rng(KEYSLOT_SWITCH_DEVICEKEY); se_initialize_rng(KEYSLOT_SWITCH_DEVICEKEY);
@ -176,7 +166,7 @@ static void setup_boot_config(void) {
bootconfig_clear(); bootconfig_clear();
} else { } else {
void *bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER; void *bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER;
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER_6X; bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER_6X;
} }
flush_dcache_range((uint8_t *)bootconfig_ptr, (uint8_t *)bootconfig_ptr + sizeof(bootconfig_t)); flush_dcache_range((uint8_t *)bootconfig_ptr, (uint8_t *)bootconfig_ptr + sizeof(bootconfig_t));
@ -447,30 +437,20 @@ static void load_package2_sections(package2_meta_t *metadata, uint32_t master_ke
static void copy_warmboot_bin_to_dram() { static void copy_warmboot_bin_to_dram() {
uint8_t *warmboot_src; uint8_t *warmboot_src;
switch (exosphere_get_target_firmware()) {
case ATMOSPHERE_TARGET_FIRMWARE_100: {
case ATMOSPHERE_TARGET_FIRMWARE_200: const uint32_t target_fw = exosphere_get_target_firmware();
case ATMOSPHERE_TARGET_FIRMWARE_300: if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
default:
generic_panic();
break;
case ATMOSPHERE_TARGET_FIRMWARE_400:
case ATMOSPHERE_TARGET_FIRMWARE_500:
warmboot_src = (uint8_t *)0x4003B000;
break;
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
warmboot_src = (uint8_t *)0x4003D800;
break;
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
case ATMOSPHERE_TARGET_FIRMWARE_910:
case ATMOSPHERE_TARGET_FIRMWARE_1000:
warmboot_src = (uint8_t *)0x4003E000; warmboot_src = (uint8_t *)0x4003E000;
break; } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
warmboot_src = (uint8_t *)0x4003D800;
} else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
warmboot_src = (uint8_t *)0x4003B000;
} else {
return;
} }
}
uint8_t *warmboot_dst = (uint8_t *)0x8000D000; uint8_t *warmboot_dst = (uint8_t *)0x8000D000;
const size_t warmboot_size = 0x2000; const size_t warmboot_size = 0x2000;
@ -522,40 +502,31 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
setup_se(); setup_se();
/* Perform initial PMC register writes, if relevant. */ /* Perform initial PMC register writes, if relevant. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000; MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000;
MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF; MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF;
MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE; MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE;
MAKE_REG32(PMC_BASE + 0x334) |= 0x10; MAKE_REG32(PMC_BASE + 0x334) |= 0x10;
switch (exosphere_get_target_firmware()) {
case ATMOSPHERE_TARGET_FIRMWARE_400: const uint32_t target_fw = exosphere_get_target_firmware();
if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
MAKE_REG32(PMC_BASE + 0x360) = 0x105; MAKE_REG32(PMC_BASE + 0x360) = 0x105;
break; } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_9_1_0) {
case ATMOSPHERE_TARGET_FIRMWARE_500:
MAKE_REG32(PMC_BASE + 0x360) = 6;
break;
case ATMOSPHERE_TARGET_FIRMWARE_600:
MAKE_REG32(PMC_BASE + 0x360) = 0x87;
break;
case ATMOSPHERE_TARGET_FIRMWARE_620:
MAKE_REG32(PMC_BASE + 0x360) = 0xA8;
break;
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
MAKE_REG32(PMC_BASE + 0x360) = 0x129;
break;
case ATMOSPHERE_TARGET_FIRMWARE_810:
MAKE_REG32(PMC_BASE + 0x360) = 0x14A;
break;
case ATMOSPHERE_TARGET_FIRMWARE_900:
MAKE_REG32(PMC_BASE + 0x360) = 0x16B;
break;
case ATMOSPHERE_TARGET_FIRMWARE_910:
MAKE_REG32(PMC_BASE + 0x360) = 0x18C; MAKE_REG32(PMC_BASE + 0x360) = 0x18C;
break; } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0) {
case ATMOSPHERE_TARGET_FIRMWARE_1000: MAKE_REG32(PMC_BASE + 0x360) = 0x16B;
MAKE_REG32(PMC_BASE + 0x360) = 0x1AD; } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
break; MAKE_REG32(PMC_BASE + 0x360) = 0x14A;
} else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
MAKE_REG32(PMC_BASE + 0x360) = 0x129;
} else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
MAKE_REG32(PMC_BASE + 0x360) = 0x0A8;
} else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
MAKE_REG32(PMC_BASE + 0x360) = 0x087;
} else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
MAKE_REG32(PMC_BASE + 0x360) = 0x006;
} else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
MAKE_REG32(PMC_BASE + 0x360) = 0x105;
} }
} }
@ -587,7 +558,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
setup_boot_config(); setup_boot_config();
/* Set sysctr0 registers based on bootconfig. */ /* Set sysctr0 registers based on bootconfig. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
uint64_t sysctr0_val = bootconfig_get_value_for_sysctr0(); uint64_t sysctr0_val = bootconfig_get_value_for_sysctr0();
MAKE_SYSCTR0_REG(0x8) = (uint32_t)((sysctr0_val >> 0) & 0xFFFFFFFFULL); MAKE_SYSCTR0_REG(0x8) = (uint32_t)((sysctr0_val >> 0) & 0xFFFFFFFFULL);
MAKE_SYSCTR0_REG(0xC) = (uint32_t)((sysctr0_val >> 32) & 0xFFFFFFFFULL); MAKE_SYSCTR0_REG(0xC) = (uint32_t)((sysctr0_val >> 32) & 0xFFFFFFFFULL);
@ -595,10 +566,10 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
} }
/* Synchronize with NX BOOTLOADER. */ /* Synchronize with NX BOOTLOADER. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X); sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X);
copy_warmboot_bin_to_dram(); copy_warmboot_bin_to_dram();
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
setup_dram_magic_numbers(); setup_dram_magic_numbers();
} }
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X); sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X);
@ -651,7 +622,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
} }
/* Synchronize with NX BOOTLOADER. */ /* Synchronize with NX BOOTLOADER. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X); sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X);
setup_4x_mmio(); setup_4x_mmio();
} else { } else {

View file

@ -26,7 +26,7 @@
/* Physaddr 0x40002EF8 */ /* Physaddr 0x40002EF8 */
static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) { static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) {
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX) + ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (0x000ull) : (0xE00ull)); return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX) + ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? (0x000ull) : (0xE00ull));
} }
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (get_nx_bootloader_mailbox_base(targetfw)) #define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (get_nx_bootloader_mailbox_base(targetfw))

View file

@ -90,14 +90,14 @@ static void mitigate_jamais_vu(void) {
} }
/* For debugging, make this check always pass. */ /* For debugging, make this check always pass. */
if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3)) { if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0 || (get_debug_authentication_status() & 3) == 3)) {
FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000;
} else { } else {
FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000; FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000;
} }
/* Jamais Vu mitigation #2: Ensure the BPMP is halted. */ /* Jamais Vu mitigation #2: Ensure the BPMP is halted. */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0 || (get_debug_authentication_status() & 3) == 3) {
/* BPMP should just be plainly halted, in debugging conditions. */ /* BPMP should just be plainly halted, in debugging conditions. */
if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x50000000) { if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x50000000) {
generic_panic(); generic_panic();
@ -167,7 +167,7 @@ static void save_tzram_state(void) {
uint8_t *tzram_encryption_dst = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM)); uint8_t *tzram_encryption_dst = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM));
uint8_t *tzram_encryption_src = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM)); uint8_t *tzram_encryption_src = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM));
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
tzram_encryption_src += 0x2000ull; tzram_encryption_src += 0x2000ull;
} }
uint8_t *tzram_store_address = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_TZRAM)); uint8_t *tzram_store_address = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_TZRAM));
@ -204,7 +204,7 @@ static void save_tzram_state(void) {
APBDEV_PMC_SEC_DISABLE8_0 = 0x550000; APBDEV_PMC_SEC_DISABLE8_0 = 0x550000;
/* Perform pre-2.0.0 PMC writes. */ /* Perform pre-2.0.0 PMC writes. */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_200) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
/* TODO: Give these writes appropriate defines in pmc.h */ /* TODO: Give these writes appropriate defines in pmc.h */
/* Save Encrypted context location + lock scratch register. */ /* Save Encrypted context location + lock scratch register. */
@ -272,7 +272,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen
notify_pmic_shutdown(); notify_pmic_shutdown();
/* Validate that the shutdown has correct context. */ /* Validate that the shutdown has correct context. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
mitigate_jamais_vu(); mitigate_jamais_vu();
} }
@ -280,7 +280,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen
configure_pmc_for_deep_powerdown(); configure_pmc_for_deep_powerdown();
/* Ensure that BPMP SC7 firmware is active. */ /* Ensure that BPMP SC7 firmware is active. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
setup_bpmp_sc7_firmware(); setup_bpmp_sc7_firmware();
} }
@ -294,7 +294,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen
/* Ensure that other cores are already asleep. */ /* Ensure that other cores are already asleep. */
if (!(APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00)) { if (!(APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00)) {
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
call_with_stack_pointer(get_smc_core012_stack_address(), save_se_and_power_down_cpu); call_with_stack_pointer(get_smc_core012_stack_address(), save_se_and_power_down_cpu);
} else { } else {
save_se_and_power_down_cpu(); save_se_and_power_down_cpu();

View file

@ -37,7 +37,7 @@ static const uint8_t g_seal_key_sources[CRYPTOUSECASE_MAX_5X][0x10] = {
}; };
bool usecase_is_invalid(unsigned int usecase) { bool usecase_is_invalid(unsigned int usecase) {
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
return usecase >= CRYPTOUSECASE_MAX_5X; return usecase >= CRYPTOUSECASE_MAX_5X;
} else { } else {
return usecase >= CRYPTOUSECASE_MAX; return usecase >= CRYPTOUSECASE_MAX;

View file

@ -169,35 +169,22 @@ void set_suspend_for_debug(void) {
} }
void set_version_specific_smcs(void) { void set_version_specific_smcs(void) {
switch (exosphere_get_target_firmware()) { const uint32_t target_firmware = exosphere_get_target_firmware();
case ATMOSPHERE_TARGET_FIRMWARE_100: if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
/* 1.0.0 doesn't have ConfigureCarveout or ReadWriteRegister. */
g_smc_priv_table[7].handler = NULL;
g_smc_priv_table[8].handler = NULL;
/* 1.0.0 doesn't have UnwrapAesWrappedTitlekey. */
g_smc_user_table[0x12].handler = NULL;
break;
case ATMOSPHERE_TARGET_FIRMWARE_200:
case ATMOSPHERE_TARGET_FIRMWARE_300:
case ATMOSPHERE_TARGET_FIRMWARE_400:
/* Do nothing. */
break;
case ATMOSPHERE_TARGET_FIRMWARE_500:
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
case ATMOSPHERE_TARGET_FIRMWARE_910:
case ATMOSPHERE_TARGET_FIRMWARE_1000:
/* No more LoadSecureExpModKey. */ /* No more LoadSecureExpModKey. */
g_smc_user_table[0xE].handler = NULL; g_smc_user_table[0xE].handler = NULL;
g_smc_user_table[0xC].id = 0xC300D60C; g_smc_user_table[0xC].id = 0xC300D60C;
g_smc_user_table[0xC].handler = smc_encrypt_rsa_key_for_import; g_smc_user_table[0xC].handler = smc_encrypt_rsa_key_for_import;
g_smc_user_table[0xD].handler = smc_decrypt_or_import_rsa_key; g_smc_user_table[0xD].handler = smc_decrypt_or_import_rsa_key;
break; } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
default: /* Nothing to do. */
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_1_0_0) {
/* 1.0.0 doesn't have ConfigureCarveout or ReadWriteRegister. */
g_smc_priv_table[7].handler = NULL;
g_smc_priv_table[8].handler = NULL;
/* 1.0.0 doesn't have UnwrapAesWrappedTitlekey. */
g_smc_user_table[0x12].handler = NULL;
} else {
panic_predefined(0xA); panic_predefined(0xA);
} }
} }
@ -306,7 +293,7 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) {
#endif #endif
/* Call function. */ /* Call function. */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_800 || if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_8_0_0 ||
(g_smc_tables[handler_id].handlers[smc_id].blacklist_mask & g_smc_blacklist_mask) == 0) { (g_smc_tables[handler_id].handlers[smc_id].blacklist_mask & g_smc_blacklist_mask) == 0) {
args->X[0] = smc_handler(args); args->X[0] = smc_handler(args);
} else { } else {
@ -636,7 +623,7 @@ uint32_t smc_read_write_register(smc_args_t *args) {
return 2; return 2;
} }
} else { } else {
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
static const uint8_t mc_whitelist_5x[0xD00/(sizeof(uint32_t) * 8)] = { static const uint8_t mc_whitelist_5x[0xD00/(sizeof(uint32_t) * 8)] = {
0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01, 0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -687,7 +674,7 @@ uint32_t smc_read_write_register(smc_args_t *args) {
break; break;
} }
} }
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
if (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address && address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + 0xD00) { if (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address && address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + 0xD00) {
/* Memory Controller RW supported only on 4.0.0+ */ /* Memory Controller RW supported only on 4.0.0+ */
static const uint8_t mc_whitelist[0x68] = { static const uint8_t mc_whitelist[0x68] = {
@ -730,7 +717,7 @@ uint32_t smc_read_write_register(smc_args_t *args) {
/* Return old value. */ /* Return old value. */
args->X[1] = old_value; args->X[1] = old_value;
return 0; return 0;
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400 && (address == 0x7001923C || address == 0x70019298)) { } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0 && (address == 0x7001923C || address == 0x70019298)) {
/* These addresses are not allowed by the whitelist. */ /* These addresses are not allowed by the whitelist. */
/* They correspond to SMMU DISABLE for the BPMP, and for APB-DMA. */ /* They correspond to SMMU DISABLE for the BPMP, and for APB-DMA. */
/* However, smcReadWriteRegister returns 0 for these addresses despite not actually performing the write. */ /* However, smcReadWriteRegister returns 0 for these addresses despite not actually performing the write. */
@ -759,7 +746,7 @@ uint32_t smc_configure_carveout(smc_args_t *args) {
} }
/* Configuration is one-shot, and cannot be done multiple times. */ /* Configuration is one-shot, and cannot be done multiple times. */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_300) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
if (g_configured_carveouts[carveout_id]) { if (g_configured_carveouts[carveout_id]) {
return 2; return 2;
} }

View file

@ -122,23 +122,10 @@ static void validate_rsa_result(unsigned int which) {
} }
static bool is_user_keyslot_valid(unsigned int keyslot) { static bool is_user_keyslot_valid(unsigned int keyslot) {
switch (exosphere_get_target_firmware()) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
case ATMOSPHERE_TARGET_FIRMWARE_100:
case ATMOSPHERE_TARGET_FIRMWARE_200:
case ATMOSPHERE_TARGET_FIRMWARE_300:
case ATMOSPHERE_TARGET_FIRMWARE_400:
case ATMOSPHERE_TARGET_FIRMWARE_500:
return keyslot <= 3;
case ATMOSPHERE_TARGET_FIRMWARE_600:
case ATMOSPHERE_TARGET_FIRMWARE_620:
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
case ATMOSPHERE_TARGET_FIRMWARE_910:
case ATMOSPHERE_TARGET_FIRMWARE_1000:
default:
return keyslot <= 5; return keyslot <= 5;
} else {
return keyslot <= 3;
} }
} }
@ -262,7 +249,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) {
uint8_t mask_id = (uint8_t)((packed_options >> 1) & 3); uint8_t mask_id = (uint8_t)((packed_options >> 1) & 3);
/* Switches the output based on how it will be used. */ /* Switches the output based on how it will be used. */
uint8_t usecase = (uint8_t)((packed_options >> 5) & (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500 ? 7 : 3)); uint8_t usecase = (uint8_t)((packed_options >> 5) & (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ? 7 : 3));
/* Switched the output based on whether it should be console unique. */ /* Switched the output based on whether it should be console unique. */
bool is_personalized = (int)(packed_options & 1); bool is_personalized = (int)(packed_options & 1);
@ -270,7 +257,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) {
bool is_recovery_boot = configitem_is_recovery_boot(); bool is_recovery_boot = configitem_is_recovery_boot();
/* 5.0.0+ Bounds checking. */ /* 5.0.0+ Bounds checking. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
if (is_personalized) { if (is_personalized) {
if (master_key_rev >= MASTERKEY_REVISION_MAX || (MASTERKEY_REVISION_300 <= master_key_rev && master_key_rev < MASTERKEY_REVISION_400_410)) { if (master_key_rev >= MASTERKEY_REVISION_MAX || (MASTERKEY_REVISION_300 <= master_key_rev && master_key_rev < MASTERKEY_REVISION_400_410)) {
return 2; return 2;
@ -324,9 +311,9 @@ uint32_t user_generate_aes_kek(smc_args_t *args) {
unsigned int keyslot; unsigned int keyslot;
if (is_personalized) { if (is_personalized) {
/* Behavior changed in 4.0.0, and in 5.0.0. */ /* Behavior changed in 4.0.0, and in 5.0.0. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
keyslot = devkey_get_keyslot(master_key_rev); keyslot = devkey_get_keyslot(master_key_rev);
} else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_400) { } else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
if (master_key_rev >= 1) { if (master_key_rev >= 1) {
keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */ keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */
} else { } else {
@ -399,7 +386,7 @@ uint32_t user_crypt_aes(smc_args_t *args) {
uint32_t keyslot = args->X[1] & 3; uint32_t keyslot = args->X[1] & 3;
uint32_t mode = (args->X[1] >> 4) & 3; uint32_t mode = (args->X[1] >> 4) & 3;
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
keyslot = args->X[1] & 7; keyslot = args->X[1] & 7;
} }
@ -415,7 +402,7 @@ uint32_t user_crypt_aes(smc_args_t *args) {
return 2; return 2;
} }
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
/* Disallow dma lists outside of safe range. */ /* Disallow dma lists outside of safe range. */
if (in_ll_paddr - 0x80000000 >= 0x3FF7F5) { if (in_ll_paddr - 0x80000000 >= 0x3FF7F5) {
return 2; return 2;
@ -463,7 +450,7 @@ uint32_t user_generate_specific_aes_key(smc_args_t *args) {
if (master_key_rev > 0) { if (master_key_rev > 0) {
master_key_rev -= 1; master_key_rev -= 1;
} }
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
master_key_rev = 0; master_key_rev = 0;
} }
@ -479,9 +466,9 @@ uint32_t user_generate_specific_aes_key(smc_args_t *args) {
unsigned int keyslot; unsigned int keyslot;
/* Behavior changed in 5.0.0. */ /* Behavior changed in 5.0.0. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
keyslot = devkey_get_keyslot(master_key_rev); keyslot = devkey_get_keyslot(master_key_rev);
} else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_400) { } else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
if (master_key_rev >= 1) { if (master_key_rev >= 1) {
keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */ keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */
} else { } else {
@ -560,7 +547,7 @@ uint32_t user_load_rsa_oaep_key(smc_args_t *args) {
upage_ref_t page_ref; upage_ref_t page_ref;
/* This function no longer exists in 5.x+. */ /* This function no longer exists in 5.x+. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
generic_panic(); generic_panic();
} }
@ -609,7 +596,7 @@ uint32_t user_decrypt_rsa_private_key(smc_args_t *args) {
upage_ref_t page_ref; upage_ref_t page_ref;
/* This function no longer exists in 5.x+. */ /* This function no longer exists in 5.x+. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
generic_panic(); generic_panic();
} }
@ -667,7 +654,7 @@ uint32_t user_load_secure_exp_mod_key(smc_args_t *args) {
upage_ref_t page_ref; upage_ref_t page_ref;
/* This function no longer exists in 5.x+. */ /* This function no longer exists in 5.x+. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
generic_panic(); generic_panic();
} }
@ -723,7 +710,7 @@ uint32_t user_secure_exp_mod(smc_args_t *args) {
void *user_modulus = (void *)args->X[2]; void *user_modulus = (void *)args->X[2];
unsigned int exponent_id = 1; unsigned int exponent_id = 1;
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
switch (args->X[3]) { switch (args->X[3]) {
case 0: case 0:
exponent_id = 1; exponent_id = 1;
@ -753,7 +740,7 @@ uint32_t user_secure_exp_mod(smc_args_t *args) {
set_exp_mod_result(3); set_exp_mod_result(3);
/* Hardcode RSA keyslot 0. */ /* Hardcode RSA keyslot 0. */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_1000) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[exponent_id], 0x100); set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[exponent_id], 0x100);
se_exp_mod(0, input, 0x100, exp_mod_done_handler); se_exp_mod(0, input, 0x100, exp_mod_done_handler);
} else if (load_imported_rsa_keypair(0, exponent_id)) { } else if (load_imported_rsa_keypair(0, exponent_id)) {
@ -780,7 +767,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
unsigned int option = (unsigned int)args->X[7]; unsigned int option = (unsigned int)args->X[7];
unsigned int master_key_rev; unsigned int master_key_rev;
unsigned int titlekey_type; unsigned int titlekey_type;
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
master_key_rev = option & 0x3F; master_key_rev = option & 0x3F;
titlekey_type = (option >> 6) & 1; titlekey_type = (option >> 6) & 1;
} else { } else {
@ -792,7 +779,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
master_key_rev -= 1; master_key_rev -= 1;
} }
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_300) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
if (master_key_rev >= MASTERKEY_REVISION_MAX) { if (master_key_rev >= MASTERKEY_REVISION_MAX) {
return 2; return 2;
} }
@ -857,7 +844,7 @@ uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) {
if (master_key_rev > 0) { if (master_key_rev > 0) {
master_key_rev -= 1; master_key_rev -= 1;
} }
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_300) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
if (master_key_rev >= MASTERKEY_REVISION_MAX) { if (master_key_rev >= MASTERKEY_REVISION_MAX) {
return 2; return 2;
} }
@ -953,7 +940,7 @@ uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args) {
upage_ref_t page_ref; upage_ref_t page_ref;
/* This function only exists in 5.x+. */ /* This function only exists in 5.x+. */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_500) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
generic_panic(); generic_panic();
} }
@ -1019,7 +1006,7 @@ uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args) {
} }
/* Modulus import isn't implemented on < 10.0.0. */ /* Modulus import isn't implemented on < 10.0.0. */
import_modulus &= (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_1000); import_modulus &= (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0);
/* Import the key. */ /* Import the key. */
import_rsa_exponent(exponent_id, user_data, 0x100); import_rsa_exponent(exponent_id, user_data, 0x100);

View file

@ -40,7 +40,7 @@ void tkey_set_master_key_rev(unsigned int master_key_rev) {
} }
static void tkey_validate_type(unsigned int type) { static void tkey_validate_type(unsigned int type) {
if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_600)) { if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_6_0_0)) {
generic_panic(); generic_panic();
} }
} }

View file

@ -25,7 +25,7 @@
#undef MC_BASE #undef MC_BASE
#define MC_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC)) #define MC_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC))
#define WARMBOOT_GET_TZRAM_SEGMENT_PA(x) ((g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) \ #define WARMBOOT_GET_TZRAM_SEGMENT_PA(x) ((g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) \
? TZRAM_GET_SEGMENT_PA(x) : TZRAM_GET_SEGMENT_5X_PA(x)) ? TZRAM_GET_SEGMENT_PA(x) : TZRAM_GET_SEGMENT_5X_PA(x))
/* start.s */ /* start.s */
@ -53,7 +53,7 @@ void warmboot_crt0_critical_section_enter(volatile critical_section_t *critical_
} }
void init_dma_controllers(unsigned int target_firmware) { void init_dma_controllers(unsigned int target_firmware) {
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
/* Set some unknown registers in HOST1X. */ /* Set some unknown registers in HOST1X. */
MAKE_REG32(0x500038F8) &= 0xFFFFFFFE; MAKE_REG32(0x500038F8) &= 0xFFFFFFFE;
MAKE_REG32(0x50003300) = 0; MAKE_REG32(0x50003300) = 0;
@ -213,7 +213,7 @@ void warmboot_init(void) {
/*identity_remap_tzram();*/ /*identity_remap_tzram();*/
/* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */ /* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */
if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) { if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
set_memory_registers_enable_mmu_1x_ttbr0(); set_memory_registers_enable_mmu_1x_ttbr0();
} else { } else {
set_memory_registers_enable_mmu_5x_ttbr0(); set_memory_registers_enable_mmu_5x_ttbr0();

View file

@ -87,15 +87,15 @@ void __attribute__((noreturn)) warmboot_main(void) {
/* Make PMC (2.x+), MC (4.x+) registers secure-only */ /* Make PMC (2.x+), MC (4.x+) registers secure-only */
secure_additional_devices(); secure_additional_devices();
if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) || if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ||
((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_800) && configitem_get_hardware_type() == 0) || ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) && configitem_get_hardware_type() == 0) ||
(configitem_is_hiz_mode_enabled())) { (configitem_is_hiz_mode_enabled())) {
warmboot_configure_hiz_mode(); warmboot_configure_hiz_mode();
} }
clear_user_smc_in_progress(); clear_user_smc_in_progress();
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
setup_4x_mmio(); setup_4x_mmio();
} }
} }

View file

@ -206,7 +206,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1)); uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
/* Firmware from versions 1.0.0 to 3.0.2. */ /* Firmware from versions 1.0.0 to 3.0.2. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
if (hardware_type >= 1) { if (hardware_type >= 1) {
return (hardware_type > 2) ? 3 : hardware_type - 1; return (hardware_type > 2) ? 3 : hardware_type - 1;
@ -215,7 +215,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
} else { } else {
return 3; return 3;
} }
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */ } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* Firmware versions from 4.0.0 to 6.2.0. */
static const uint32_t types[] = {0,1,4,3}; static const uint32_t types[] = {0,1,4,3};
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C); hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
hardware_type--; hardware_type--;

View file

@ -206,7 +206,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1)); uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
/* Firmware from versions 1.0.0 to 3.0.2. */ /* Firmware from versions 1.0.0 to 3.0.2. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
if (hardware_type >= 1) { if (hardware_type >= 1) {
return (hardware_type > 2) ? 3 : hardware_type - 1; return (hardware_type > 2) ? 3 : hardware_type - 1;
@ -215,7 +215,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
} else { } else {
return 3; return 3;
} }
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */ } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* Firmware versions from 4.0.0 to 6.2.0. */
static const uint32_t types[] = {0,1,4,3}; static const uint32_t types[] = {0,1,4,3};
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C); hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
hardware_type--; hardware_type--;

View file

@ -50,6 +50,7 @@ typedef struct device_partition_t {
device_partition_cipher_t read_cipher; /* Cipher for read operations. */ device_partition_cipher_t read_cipher; /* Cipher for read operations. */
device_partition_cipher_t write_cipher; /* Cipher for write operations. */ device_partition_cipher_t write_cipher; /* Cipher for write operations. */
DevicePartitionCryptoMode crypto_mode; /* Mode to use for cryptographic operations. */ DevicePartitionCryptoMode crypto_mode; /* Mode to use for cryptographic operations. */
size_t crypto_sector_size;
device_partition_initializer_t initializer; /* Initializer. */ device_partition_initializer_t initializer; /* Initializer. */
device_partition_finalizer_t finalizer; /* Finalizer. */ device_partition_finalizer_t finalizer; /* Finalizer. */

View file

@ -289,6 +289,20 @@ int fsdev_unmount_device(const char *name) {
return ret; return ret;
} }
int fsdev_register_keys(const char *name, unsigned int target_firmware, BisPartition part) {
fsdev_device_t *device = fsdev_find_device(name);
if (device == NULL) {
errno = ENOENT;
return -1;
}
derive_bis_key(device->devpart.keys, part, target_firmware);
return 0;
}
int fsdev_unmount_all(void) { int fsdev_unmount_all(void) {
for (size_t i = 0; i < FF_VOLUMES; i++) { for (size_t i = 0; i < FF_VOLUMES; i++) {
int ret = fsdev_unmount_device(g_fsdev_devices[i].name); int ret = fsdev_unmount_device(g_fsdev_devices[i].name);

View file

@ -21,12 +21,15 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "device_partition.h" #include "device_partition.h"
#include "key_derivation.h"
int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately); int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately);
int fsdev_register_device(const char *name); int fsdev_register_device(const char *name);
int fsdev_unregister_device(const char *name); int fsdev_unregister_device(const char *name);
int fsdev_unmount_device(const char *name); /* also unregisters. */ int fsdev_unmount_device(const char *name); /* also unregisters. */
int fsdev_register_keys(const char *name, unsigned int target_firmware, BisPartition part);
int fsdev_set_attr(const char *file, int attr, int mask); /* Non-standard function to set file DOS attributes. */ int fsdev_set_attr(const char *file, int attr, int mask); /* Non-standard function to set file DOS attributes. */
int fsdev_get_attr(const char *file); /* Non-standard function to get file DOS attributes. */ int fsdev_get_attr(const char *file); /* Non-standard function to get file DOS attributes. */

View file

@ -16,7 +16,9 @@
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "lib/fatfs/ff.h"
#include "fs_utils.h" #include "fs_utils.h"
#include "fs_dev.h"
size_t get_file_size(const char *filename) { size_t get_file_size(const char *filename) {
struct stat st; struct stat st;
@ -66,3 +68,26 @@ bool is_valid_file(const char *path) {
return false; return false;
} }
bool is_valid_concatenation_file(const char *path) {
if (is_valid_file(path)) {
return true;
} else if (is_valid_folder(path)) {
/* Check if the archive bit is set. */
int rc = fsdev_get_attr(path);
/* Failed to get file DOS attributes. */
if (rc == -1) {
return false;
}
/* Check if our path is not a directory (it should be if we're in this code, though...). */
if (!(rc & AM_DIR)) {
return false;
}
return (rc & AM_ARC) != 0;
} else {
return false;
}
}

View file

@ -25,4 +25,6 @@ size_t dump_to_file(const void *src, size_t src_size, const char *filename);
bool is_valid_folder(const char *path); bool is_valid_folder(const char *path);
bool is_valid_file(const char *path); bool is_valid_file(const char *path);
bool is_valid_concatenation_file(const char *path);
#endif #endif

View file

@ -206,7 +206,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1)); uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
/* Firmware from versions 1.0.0 to 3.0.2. */ /* Firmware from versions 1.0.0 to 3.0.2. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
if (hardware_type >= 1) { if (hardware_type >= 1) {
return (hardware_type > 2) ? 3 : hardware_type - 1; return (hardware_type > 2) ? 3 : hardware_type - 1;
@ -215,7 +215,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
} else { } else {
return 3; return 3;
} }
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */ } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* Firmware versions from 4.0.0 to 6.2.0. */
static const uint32_t types[] = {0,1,4,3}; static const uint32_t types[] = {0,1,4,3};
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C); hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
hardware_type--; hardware_type--;
@ -261,3 +261,12 @@ void fuse_get_hardware_info(void *dst) {
memcpy(dst, hw_info, 0x10); memcpy(dst, hw_info, 0x10);
} }
/* Get the Key Generation value. */
uint32_t fuse_get_5x_key_generation(void) {
if ((fuse_get_reserved_odm(4) & 0x800) && (fuse_get_reserved_odm(0) == 0x8E61ECAE) && (fuse_get_reserved_odm(1) == 0xF2BA3BB2)) {
return (fuse_get_reserved_odm(2) & 0x1F);
} else {
return 0;
}
}

View file

@ -219,6 +219,7 @@ uint32_t fuse_get_dram_id(void);
uint32_t fuse_get_hardware_type(uint32_t target_firmware); uint32_t fuse_get_hardware_type(uint32_t target_firmware);
uint32_t fuse_get_retail_type(void); uint32_t fuse_get_retail_type(void);
void fuse_get_hardware_info(void *dst); void fuse_get_hardware_info(void *dst);
uint32_t fuse_get_5x_key_generation(void);
uint32_t fuse_hw_read(uint32_t addr); uint32_t fuse_hw_read(uint32_t addr);
void fuse_hw_write(uint32_t value, uint32_t addr); void fuse_hw_write(uint32_t value, uint32_t addr);

View file

@ -15,6 +15,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include "lib/log.h"
#include "key_derivation.h" #include "key_derivation.h"
#include "masterkey.h" #include "masterkey.h"
#include "se.h" #include "se.h"
@ -143,29 +144,16 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
} }
/* Do 6.2.0+ keygen. */ /* Do 6.2.0+ keygen. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
uint32_t desired_keyblob; uint32_t desired_keyblob;
switch (target_firmware) {
case ATMOSPHERE_TARGET_FIRMWARE_620: if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
desired_keyblob = MASTERKEY_REVISION_620; /* NOTE: We load in the current key for all >= 8.1.0 firmwares to reduce sept binaries. */
break;
case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800:
desired_keyblob = MASTERKEY_REVISION_700_800;
break;
case ATMOSPHERE_TARGET_FIRMWARE_810:
desired_keyblob = MASTERKEY_REVISION_810;
/* Fallthrough */
case ATMOSPHERE_TARGET_FIRMWARE_900:
desired_keyblob = MASTERKEY_REVISION_900;
/* Fallthrough */
case ATMOSPHERE_TARGET_FIRMWARE_910:
case ATMOSPHERE_TARGET_FIRMWARE_1000:
desired_keyblob = MASTERKEY_REVISION_910_CURRENT; desired_keyblob = MASTERKEY_REVISION_910_CURRENT;
break; } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
default: desired_keyblob = MASTERKEY_REVISION_700_800;
fatal_error("Unknown target firmware: %02x!", target_firmware); } else {
break; desired_keyblob = MASTERKEY_REVISION_620;
} }
/* Try emulation result. */ /* Try emulation result. */
@ -213,31 +201,31 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
set_aes_keyslot(0xC, g_dec_keyblobs[available_revision].master_kek, 0x10); set_aes_keyslot(0xC, g_dec_keyblobs[available_revision].master_kek, 0x10);
/* Also set the Package1 key for the revision that is stored on the eMMC boot0 partition. */ /* Also set the Package1 key for the revision that is stored on the eMMC boot0 partition. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_620) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
load_package1_key(available_revision); load_package1_key(available_revision);
} }
/* Derive keys for Exosphere, lock critical keyslots. */ /* Derive keys for Exosphere, lock critical keyslots. */
switch (target_firmware) { switch (target_firmware) {
case ATMOSPHERE_TARGET_FIRMWARE_100: case ATMOSPHERE_TARGET_FIRMWARE_1_0_0:
case ATMOSPHERE_TARGET_FIRMWARE_200: case ATMOSPHERE_TARGET_FIRMWARE_2_0_0:
case ATMOSPHERE_TARGET_FIRMWARE_300: case ATMOSPHERE_TARGET_FIRMWARE_3_0_0:
decrypt_data_into_keyslot(0xD, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xD, 0xF, devicekey_seed, 0x10);
decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10); decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10);
break; break;
case ATMOSPHERE_TARGET_FIRMWARE_400: case ATMOSPHERE_TARGET_FIRMWARE_4_0_0:
decrypt_data_into_keyslot(0xD, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xD, 0xF, devicekey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10); decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10);
break; break;
case ATMOSPHERE_TARGET_FIRMWARE_500: case ATMOSPHERE_TARGET_FIRMWARE_5_0_0:
case ATMOSPHERE_TARGET_FIRMWARE_600: case ATMOSPHERE_TARGET_FIRMWARE_6_0_0:
case ATMOSPHERE_TARGET_FIRMWARE_620: case ATMOSPHERE_TARGET_FIRMWARE_6_2_0:
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_7_0_0:
case ATMOSPHERE_TARGET_FIRMWARE_800: case ATMOSPHERE_TARGET_FIRMWARE_8_0_0:
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_8_1_0:
case ATMOSPHERE_TARGET_FIRMWARE_900: case ATMOSPHERE_TARGET_FIRMWARE_9_0_0:
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10);
@ -254,11 +242,13 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
/* Sets final keyslot flags, for handover to TZ/Exosphere. Setting these will prevent the BPMP from using the device key or master key. */ /* Sets final keyslot flags, for handover to TZ/Exosphere. Setting these will prevent the BPMP from using the device key or master key. */
void finalize_nx_keydata(uint32_t target_firmware) { void finalize_nx_keydata(uint32_t target_firmware) {
set_aes_keyslot_flags(0xC, 0xFF); set_aes_keyslot_flags(0xC, 0xFF);
set_aes_keyslot_flags((target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY), 0xFF); set_aes_keyslot_flags((target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY), 0xFF);
} }
static void generate_specific_aes_key(void *dst, const void *wrapped_key, bool should_mask, uint32_t target_firmware) { static void generate_specific_aes_key(void *dst, const void *wrapped_key, bool should_mask, uint32_t target_firmware, uint32_t generation) {
unsigned int keyslot = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY); unsigned int keyslot = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ? (devkey_get_keyslot(generation)) : (KEYSLOT_SWITCH_DEVICEKEY);
if (fuse_get_bootrom_patch_version() < 0x7F) { if (fuse_get_bootrom_patch_version() < 0x7F) {
/* On dev units, use a fixed "all-zeroes" seed. */ /* On dev units, use a fixed "all-zeroes" seed. */
/* Yes, this data really is all-zero in actual TrustZone .rodata. */ /* Yes, this data really is all-zero in actual TrustZone .rodata. */
@ -281,7 +271,7 @@ static void generate_specific_aes_key(void *dst, const void *wrapped_key, bool s
} }
} }
static void generate_personalized_aes_key_for_bis(void *dst, const void *wrapped_kek, const void *wrapped_key, uint32_t target_firmware) { static void generate_personalized_aes_key_for_bis(void *dst, const void *wrapped_kek, const void *wrapped_key, uint32_t target_firmware, uint32_t generation) {
static const uint8_t AL16 kek_source[0x10] = { static const uint8_t AL16 kek_source[0x10] = {
0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9 0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9
}; };
@ -289,7 +279,7 @@ static void generate_personalized_aes_key_for_bis(void *dst, const void *wrapped
0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8 0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8
}; };
unsigned int keyslot = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY); unsigned int keyslot = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ? (devkey_get_keyslot(generation)) : (KEYSLOT_SWITCH_DEVICEKEY);
/* Derive kek. */ /* Derive kek. */
decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, keyslot, kek_source, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, keyslot, kek_source, 0x10);
decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, KEYSLOT_SWITCH_TEMPKEY, wrapped_kek, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, KEYSLOT_SWITCH_TEMPKEY, wrapped_kek, 0x10);
@ -314,16 +304,18 @@ void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmwa
} }
}; };
const uint32_t bis_key_generation = fuse_get_5x_key_generation();
static const uint8_t AL16 bis_kek_source[0x10] = {0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F}; static const uint8_t AL16 bis_kek_source[0x10] = {0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F};
switch (partition_id) { switch (partition_id) {
case BisPartition_Calibration: case BisPartition_Calibration:
generate_specific_aes_key(dst, key_source_for_bis[partition_id][0], false, target_firmware); generate_specific_aes_key(dst, key_source_for_bis[partition_id][0], false, target_firmware, bis_key_generation);
generate_specific_aes_key(dst + 0x10, key_source_for_bis[partition_id][1], false, target_firmware); generate_specific_aes_key(dst + 0x10, key_source_for_bis[partition_id][1], false, target_firmware, bis_key_generation);
break; break;
case BisPartition_Safe: case BisPartition_Safe:
case BisPartition_UserSystem: case BisPartition_UserSystem:
generate_personalized_aes_key_for_bis(dst, bis_kek_source, key_source_for_bis[partition_id][0], target_firmware); generate_personalized_aes_key_for_bis(dst, bis_kek_source, key_source_for_bis[partition_id][0], target_firmware, bis_key_generation);
generate_personalized_aes_key_for_bis(dst + 0x10, bis_kek_source, key_source_for_bis[partition_id][1], target_firmware); generate_personalized_aes_key_for_bis(dst + 0x10, bis_kek_source, key_source_for_bis[partition_id][1], target_firmware, bis_key_generation);
break; break;
default: default:
generic_panic(); generic_panic();

View file

@ -17,6 +17,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <vapours/ams/ams_target_firmware.h>
#include "utils.h" #include "utils.h"
#include "masterkey.h" #include "masterkey.h"
@ -26,6 +27,7 @@ static unsigned int g_mkey_revision = 0;
static bool g_determined_mkey_revision = false; static bool g_determined_mkey_revision = false;
static uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10]; static uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10];
static uint8_t g_old_devicekeys[MASTERKEY_NUM_NEW_DEVICE_KEYS - 1][0x10];
/* TODO: Extend with new vectors, as needed. */ /* TODO: Extend with new vectors, as needed. */
/* Dev unit keys. */ /* Dev unit keys. */
@ -59,6 +61,39 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] =
{0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A}, /* Master key 09 encrypted with Master key 0A. */ {0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A}, /* Master key 09 encrypted with Master key 0A. */
}; };
static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
{0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */
{0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */
{0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.x New Device Key Source. */
{0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17}, /* 6.2.0 New Device Key Source. */
{0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, /* 7.0.0 New Device Key Source. */
{0x67, 0x62, 0xD4, 0x8E, 0x55, 0xCF, 0xFF, 0x41, 0x31, 0x15, 0x3B, 0x24, 0x0C, 0x7C, 0x07, 0xAE}, /* 8.1.0 New Device Key Source. */
{0x4A, 0xC3, 0x4E, 0x14, 0x8B, 0x96, 0x4A, 0xD5, 0xD4, 0x99, 0x73, 0xC4, 0x45, 0xAB, 0x8B, 0x49}, /* 9.0.0 New Device Key Source. */
{0x14, 0xB8, 0x74, 0x12, 0xCB, 0xBD, 0x0B, 0x8F, 0x20, 0xFB, 0x30, 0xDA, 0x27, 0xE4, 0x58, 0x94}, /* 9.1.0 New Device Key Source. */
};
static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
{0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */
{0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */
{0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.x New Device Keygen Source. */
{0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB}, /* 6.2.0 New Device Keygen Source. */
{0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */
{0xA6, 0x81, 0x71, 0xE7, 0xB5, 0x23, 0x74, 0xB0, 0x39, 0x8C, 0xB7, 0xFF, 0xA0, 0x62, 0x9F, 0x8D}, /* 8.1.0 New Device Keygen Source. */
{0x03, 0xE7, 0xEB, 0x43, 0x1B, 0xCF, 0x5F, 0xB5, 0xED, 0xDC, 0x97, 0xAE, 0x21, 0x8D, 0x19, 0xED}, /* 9.0.0 New Device Keygen Source. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
};
static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
{0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */
{0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */
{0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5}, /* 6.x New Device Keygen Source. */
{0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38}, /* 6.2.0 New Device Keygen Source. */
{0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 7.0.0 New Device Keygen Source. */
{0x94, 0xD6, 0xA8, 0xC0, 0x95, 0xAF, 0xD0, 0xA6, 0x27, 0x53, 0x5E, 0xE5, 0x8E, 0x70, 0x1F, 0x87}, /* 8.1.0 New Device Keygen Source. */
{0x61, 0x6A, 0x88, 0x21, 0xA3, 0x52, 0xB0, 0x19, 0x16, 0x25, 0xA4, 0xE3, 0x4C, 0x54, 0x02, 0x0F}, /* 9.0.0 New Device Keygen Source. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
};
static bool check_mkey_revision(unsigned int revision, bool is_retail) { static bool check_mkey_revision(unsigned int revision, bool is_retail) {
uint8_t final_vector[0x10]; uint8_t final_vector[0x10];
@ -127,3 +162,50 @@ unsigned int mkey_get_keyslot(unsigned int revision) {
return KEYSLOT_SWITCH_TEMPKEY; return KEYSLOT_SWITCH_TEMPKEY;
} }
} }
void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigned int target_firmware) {
uint8_t work_buffer[0x10];
for (unsigned int revision = 0; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS; revision++) {
const unsigned int relative_revision = revision + MASTERKEY_REVISION_400_410;
se_aes_ecb_decrypt_block(keygen_keyslot, work_buffer, 0x10, new_device_key_sources[revision], 0x10);
decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), is_retail ? new_device_keygen_sources[revision] : new_device_keygen_sources_dev[revision], 0x10);
if (relative_revision > mkey_get_revision()) {
break;
} else if (relative_revision == mkey_get_revision()) {
/* On 7.0.0, sept will have derived this key for us already. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
decrypt_data_into_keyslot(KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10);
}
} else {
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10, work_buffer, 0x10);
set_old_devkey(relative_revision, work_buffer);
}
}
set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF);
clear_aes_keyslot(keygen_keyslot);
}
void set_old_devkey(unsigned int revision, const uint8_t *key) {
if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_MAX <= revision) {
generic_panic();
}
memcpy(g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], key, 0x10);
}
unsigned int devkey_get_keyslot(unsigned int revision) {
if (!g_determined_mkey_revision || revision > g_mkey_revision) {
generic_panic();
}
if (revision < MASTERKEY_REVISION_400_410) {
return KEYSLOT_SWITCH_4XOLDDEVICEKEY;
} else if (revision < g_mkey_revision) {
/* Load into a temp keyslot. */
set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], 0x10);
return KEYSLOT_SWITCH_TEMPKEY;
} else {
return KEYSLOT_SWITCH_DEVICEKEY;
}
}

View file

@ -41,7 +41,11 @@ int mkey_detect_revision(bool is_retail);
unsigned int mkey_get_revision(void); unsigned int mkey_get_revision(void);
unsigned int mkey_get_keyslot(unsigned int revision); unsigned int mkey_get_keyslot(unsigned int revision);
void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigned int target_firmware);
void set_old_devkey(unsigned int revision, const uint8_t *key); void set_old_devkey(unsigned int revision, const uint8_t *key);
unsigned int devkey_get_keyslot(unsigned int revision); unsigned int devkey_get_keyslot(unsigned int revision);
#endif #endif

View file

@ -218,41 +218,110 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
return 1; return 1;
} }
static bool is_nca_present(const char *nca_name) {
char path[0x100];
snprintf(path, sizeof(path), "system:/contents/registered/%s.nca", nca_name);
return is_valid_concatenation_file(path);
}
static uint32_t nxboot_get_specific_target_firmware(uint32_t target_firmware){
#define CHECK_NCA(NCA_ID, VERSION) do { if (is_nca_present(NCA_ID)) { return ATMOSPHERE_TARGET_FIRMWARE_##VERSION; } } while(0)
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
CHECK_NCA("e951bc9dedcd54f65ffd83d4d050f9e0", 10_0_2);
CHECK_NCA("36ab1acf0c10a2beb9f7d472685f9a89", 10_0_1);
CHECK_NCA("5625cdc21d5f1ca52f6c36ba261505b9", 10_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_1_0) {
CHECK_NCA("09ef4d92bb47b33861e695ba524a2c17", 9_2_0);
CHECK_NCA("c5fbb49f2e3648c8cfca758020c53ecb", 9_1_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0) {
CHECK_NCA("fd1ffb82dc1da76346343de22edbc97c", 9_0_1);
CHECK_NCA("a6af05b33f8f903aab90c8b0fcbcc6a4", 9_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
CHECK_NCA("724d9b432929ea43e787ad81bf09ae65", 8_1_1); /* 8.1.1-100 from Lite */
CHECK_NCA("e9bb0602e939270a9348bddd9b78827b", 8_1_1); /* 8.1.1-12 from chinese gamecard */
CHECK_NCA("7eedb7006ad855ec567114be601b2a9d", 8_1_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
CHECK_NCA("6c5426d27c40288302ad616307867eba", 8_0_1);
CHECK_NCA("4fe7b4abcea4a0bcc50975c1a926efcb", 8_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
CHECK_NCA("e6b22c40bb4fa66a151f1dc8db5a7b5c", 7_0_1);
CHECK_NCA("c613bd9660478de69bc8d0e2e7ea9949", 7_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
CHECK_NCA("6dfaaf1a3cebda6307aa770d9303d9b6", 6_2_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
CHECK_NCA("1d21680af5a034d626693674faf81b02", 6_1_0);
CHECK_NCA("663e74e45ffc86fbbaeb98045feea315", 6_0_1);
CHECK_NCA("258c1786b0f6844250f34d9c6f66095b", 6_0_0); /* Release 6.0.0-5.0 */
CHECK_NCA("286e30bafd7e4197df6551ad802dd815", 6_0_0); /* Pre-Release 6.0.0-4.0 */
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
CHECK_NCA("fce3b0ea366f9c95fe6498b69274b0e7", 5_1_0);
CHECK_NCA("c5758b0cb8c6512e8967e38842d35016", 5_0_2);
CHECK_NCA("53eb605d4620e8fd50064b24fd57783a", 5_0_1);
CHECK_NCA("09a2f9c16ce1c121ae6d231b35d17515", 5_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
CHECK_NCA("77e1ae7661ad8a718b9b13b70304aeea", 4_1_0);
CHECK_NCA("d0e5d20e3260f3083bcc067483b71274", 4_0_1);
CHECK_NCA("483a24ee3fd7149f9112d1931166a678", 4_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
CHECK_NCA("704129fc89e1fcb85c37b3112e51b0fc", 3_0_2);
CHECK_NCA("1fb00543307337d523ccefa9923e0c50", 3_0_1);
CHECK_NCA("6ebd3447473bade18badbeb5032af87d", 3_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
CHECK_NCA("d1c991c53a8a9038f8c3157a553d876d", 2_3_0);
CHECK_NCA("7f90353dff2d7ce69e19e07ebc0d5489", 2_2_0);
CHECK_NCA("e9b3e75fce00e52fe646156634d229b4", 2_1_0);
CHECK_NCA("7a1f79f8184d4b9bae1755090278f52c", 2_0_0);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_1_0_0) {
CHECK_NCA("a1b287e07f8455e8192f13d0e45a2aaf", 1_0_0); /* 1.0.0 from Factory */
CHECK_NCA("117f7b9c7da3e8cef02340596af206b3", 1_0_0); /* 1.0.0 from Gamecard */
} else {
fatal_error("[NXBOOT] Unknown Target Firmware!");
}
#undef CHECK_NCA
/* If we didn't find a more specific firmware, return our package1 approximation. */
return target_firmware;
}
static uint32_t nxboot_get_target_firmware(const void *package1loader) { static uint32_t nxboot_get_target_firmware(const void *package1loader) {
const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader;
switch (package1loader_header->version) { switch (package1loader_header->version) {
case 0x01: /* 1.0.0 */ case 0x01: /* 1.0.0 */
return ATMOSPHERE_TARGET_FIRMWARE_100; return ATMOSPHERE_TARGET_FIRMWARE_1_0_0;
case 0x02: /* 2.0.0 - 2.3.0 */ case 0x02: /* 2.0.0 - 2.3.0 */
return ATMOSPHERE_TARGET_FIRMWARE_200; return ATMOSPHERE_TARGET_FIRMWARE_2_0_0;
case 0x04: /* 3.0.0 and 3.0.1 - 3.0.2 */ case 0x04: /* 3.0.0 and 3.0.1 - 3.0.2 */
return ATMOSPHERE_TARGET_FIRMWARE_300; return ATMOSPHERE_TARGET_FIRMWARE_3_0_0;
case 0x07: /* 4.0.0 - 4.1.0 */ case 0x07: /* 4.0.0 - 4.1.0 */
return ATMOSPHERE_TARGET_FIRMWARE_400; return ATMOSPHERE_TARGET_FIRMWARE_4_0_0;
case 0x0B: /* 5.0.0 - 5.1.0 */ case 0x0B: /* 5.0.0 - 5.1.0 */
return ATMOSPHERE_TARGET_FIRMWARE_500; return ATMOSPHERE_TARGET_FIRMWARE_5_0_0;
case 0x0E: { /* 6.0.0 - 6.2.0 */ case 0x0E: { /* 6.0.0 - 6.2.0 */
if (memcmp(package1loader_header->build_timestamp, "20180802", 8) == 0) { if (memcmp(package1loader_header->build_timestamp, "20180802", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_600; return ATMOSPHERE_TARGET_FIRMWARE_6_0_0;
} else if (memcmp(package1loader_header->build_timestamp, "20181107", 8) == 0) { } else if (memcmp(package1loader_header->build_timestamp, "20181107", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_620; return ATMOSPHERE_TARGET_FIRMWARE_6_2_0;
} else { } else {
fatal_error("[NXBOOT] Unable to identify package1!\n"); fatal_error("[NXBOOT] Unable to identify package1!\n");
} }
} }
case 0x0F: /* 7.0.0 - 7.0.1 */ case 0x0F: /* 7.0.0 - 7.0.1 */
return ATMOSPHERE_TARGET_FIRMWARE_700; return ATMOSPHERE_TARGET_FIRMWARE_7_0_0;
case 0x10: { /* 8.0.0 - 9.0.0 */ case 0x10: { /* 8.0.0 - 9.0.0 */
if (memcmp(package1loader_header->build_timestamp, "20190314", 8) == 0) { if (memcmp(package1loader_header->build_timestamp, "20190314", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_800; return ATMOSPHERE_TARGET_FIRMWARE_8_0_0;
} else if (memcmp(package1loader_header->build_timestamp, "20190531", 8) == 0) { } else if (memcmp(package1loader_header->build_timestamp, "20190531", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_810; return ATMOSPHERE_TARGET_FIRMWARE_8_1_0;
} else if (memcmp(package1loader_header->build_timestamp, "20190809", 8) == 0) { } else if (memcmp(package1loader_header->build_timestamp, "20190809", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_900; return ATMOSPHERE_TARGET_FIRMWARE_9_0_0;
} else if (memcmp(package1loader_header->build_timestamp, "20191021", 8) == 0) { } else if (memcmp(package1loader_header->build_timestamp, "20191021", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_910; return ATMOSPHERE_TARGET_FIRMWARE_9_1_0;
} else if (memcmp(package1loader_header->build_timestamp, "20200303", 8) == 0) { } else if (memcmp(package1loader_header->build_timestamp, "20200303", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_1000; return ATMOSPHERE_TARGET_FIRMWARE_10_0_0;
} else { } else {
fatal_error("[NXBOOT] Unable to identify package1!\n"); fatal_error("[NXBOOT] Unable to identify package1!\n");
} }
@ -424,11 +493,11 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) {
} }
} else { } else {
/* Check if fuses are < 4.0.0, but firmware is >= 4.0.0 */ /* Check if fuses are < 4.0.0, but firmware is >= 4.0.0 */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400 && !(fuse_get_reserved_odm(7) & ~0x0000000F)) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0 && !(fuse_get_reserved_odm(7) & ~0x0000000F)) {
kip_patches_set_enable_nogc(); kip_patches_set_enable_nogc();
} }
/* Check if the fuses are < 9.0.0, but firmware is >= 9.0.0 */ /* Check if the fuses are < 9.0.0, but firmware is >= 9.0.0 */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_900 && !(fuse_get_reserved_odm(7) & ~0x000003FF)) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0 && !(fuse_get_reserved_odm(7) & ~0x000003FF)) {
kip_patches_set_enable_nogc(); kip_patches_set_enable_nogc();
} }
} }
@ -516,8 +585,8 @@ static void nxboot_move_bootconfig() {
fclose(bcfile); fclose(bcfile);
/* Select the actual BootConfig size and destination address. */ /* Select the actual BootConfig size and destination address. */
bootconfig_addr = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) ? 0x4003D000 : 0x4003F800; bootconfig_addr = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_6_0_0) ? 0x4003D000 : 0x4003F800;
bootconfig_size = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x3000 : 0x1000; bootconfig_size = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ? 0x3000 : 0x1000;
/* Copy the BootConfig into IRAM. */ /* Copy the BootConfig into IRAM. */
memset((void *)bootconfig_addr, 0, bootconfig_size); memset((void *)bootconfig_addr, 0, bootconfig_size);
@ -638,6 +707,7 @@ uint32_t nxboot_main(void) {
/* Find the system's target firmware. */ /* Find the system's target firmware. */
uint32_t target_firmware = nxboot_get_target_firmware(package1loader); uint32_t target_firmware = nxboot_get_target_firmware(package1loader);
if (!target_firmware) if (!target_firmware)
fatal_error("[NXBOOT] Failed to detect target firmware!\n"); fatal_error("[NXBOOT] Failed to detect target firmware!\n");
else else
@ -685,7 +755,7 @@ uint32_t nxboot_main(void) {
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n"); fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n");
} }
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_810) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
if (fuse_get_retail_type() != 0) { if (fuse_get_retail_type() != 0) {
sept_secondary_enc = sept_secondary_01_enc; sept_secondary_enc = sept_secondary_01_enc;
sept_secondary_enc_size = sept_secondary_01_enc_size; sept_secondary_enc_size = sept_secondary_01_enc_size;
@ -694,7 +764,7 @@ uint32_t nxboot_main(void) {
sept_secondary_enc_size = sept_secondary_dev_01_enc_size; sept_secondary_enc_size = sept_secondary_dev_01_enc_size;
} }
tsec_fw_size = 0x3300; tsec_fw_size = 0x3300;
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
if (fuse_get_retail_type() != 0) { if (fuse_get_retail_type() != 0) {
sept_secondary_enc = sept_secondary_00_enc; sept_secondary_enc = sept_secondary_00_enc;
sept_secondary_enc_size = sept_secondary_00_enc_size; sept_secondary_enc_size = sept_secondary_00_enc_size;
@ -703,7 +773,7 @@ uint32_t nxboot_main(void) {
sept_secondary_enc_size = sept_secondary_dev_00_enc_size; sept_secondary_enc_size = sept_secondary_dev_00_enc_size;
} }
tsec_fw_size = 0x3000; tsec_fw_size = 0x3000;
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
tsec_fw_size = 0x2900; tsec_fw_size = 0x2900;
} else { } else {
tsec_fw_size = 0xF00; tsec_fw_size = 0xF00;
@ -715,7 +785,7 @@ uint32_t nxboot_main(void) {
/* Get the TSEC keys. */ /* Get the TSEC keys. */
uint8_t tsec_key[0x10] = {0}; uint8_t tsec_key[0x10] = {0};
uint8_t tsec_root_keys[0x20][0x10] = {0}; uint8_t tsec_root_keys[0x20][0x10] = {0};
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
/* Detect whether we need to run sept-secondary in order to derive keys. */ /* Detect whether we need to run sept-secondary in order to derive keys. */
if (!get_and_clear_has_run_sept()) { if (!get_and_clear_has_run_sept()) {
reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size);
@ -725,7 +795,7 @@ uint32_t nxboot_main(void) {
} }
} }
get_and_clear_has_run_sept(); get_and_clear_has_run_sept();
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
uint8_t tsec_keys[0x20] = {0}; uint8_t tsec_keys[0x20] = {0};
/* Emulate the TSEC payload on 6.2.0+. */ /* Emulate the TSEC payload on 6.2.0+. */
@ -746,17 +816,46 @@ uint32_t nxboot_main(void) {
/* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */ /* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */
unsigned int keygen_type = 0; unsigned int keygen_type = 0;
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) { if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) {
fatal_error("[NXBOOT] Key derivation failed!\n"); fatal_error("[NXBOOT] Key derivation failed!\n");
} }
} }
/* Derive new device keys. */
{
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
derive_new_device_keys(fuse_get_retail_type() != 0, KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, target_firmware);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
derive_new_device_keys(fuse_get_retail_type() != 0, KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY, target_firmware);
} else {
/* No new keys to derive */
}
}
/* Set the system partition's keys. */
if (fsdev_register_keys("system", target_firmware, BisPartition_UserSystem) != 0) {
fatal_error("[NXBOOT] Failed to set SYSTEM partition keys!\n");
}
/* Mount the system partition. */
if (fsdev_register_device("system") != 0) {
fatal_error("[NXBOOT] Failed to register SYSTEM partition!\n");
}
/* Lightly validate the system partition. */
if (!is_valid_folder("system:/Contents")) {
fatal_error("[NXBOOT] SYSTEM partition seems corrupted!\n");
}
/* Make the target firmware more specific. */
target_firmware = nxboot_get_specific_target_firmware(target_firmware);
/* Setup boot configuration for Exosphère. */ /* Setup boot configuration for Exosphère. */
nxboot_configure_exosphere(target_firmware, keygen_type, &exo_emummc_cfg); nxboot_configure_exosphere(target_firmware, keygen_type, &exo_emummc_cfg);
/* Initialize Boot Reason on older firmware versions. */ /* Initialize Boot Reason on older firmware versions. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Initializing Boot Reason...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Initializing Boot Reason...\n");
nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(target_firmware)); nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(target_firmware));
} }
@ -807,11 +906,11 @@ uint32_t nxboot_main(void) {
} }
/* Select the right address for the warmboot firmware. */ /* Select the right address for the warmboot firmware. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
warmboot_memaddr = (void *)0x8000D000; warmboot_memaddr = (void *)0x8000D000;
} else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) { } else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
warmboot_memaddr = (void *)0x4003B000; warmboot_memaddr = (void *)0x4003B000;
} else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { } else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
warmboot_memaddr = (void *)0x4003D800; warmboot_memaddr = (void *)0x4003D800;
} else { } else {
warmboot_memaddr = (void *)0x4003E000; warmboot_memaddr = (void *)0x4003E000;
@ -822,7 +921,7 @@ uint32_t nxboot_main(void) {
/* Copy the warmboot firmware and set the address in PMC if necessary. */ /* Copy the warmboot firmware and set the address in PMC if necessary. */
if (warmboot_fw && (warmboot_fw_size > 0)) { if (warmboot_fw && (warmboot_fw_size > 0)) {
memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size); memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size);
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0)
pmc->scratch1 = (uint32_t)warmboot_memaddr; pmc->scratch1 = (uint32_t)warmboot_memaddr;
} }
@ -842,7 +941,7 @@ uint32_t nxboot_main(void) {
print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Reading Exosphère...\n"); print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Reading Exosphère...\n");
/* Select the right address for Exosphère. */ /* Select the right address for Exosphère. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
exosphere_memaddr = (void *)0x4002D000; exosphere_memaddr = (void *)0x4002D000;
} else { } else {
exosphere_memaddr = (void *)0x4002B000; exosphere_memaddr = (void *)0x4002B000;
@ -870,7 +969,7 @@ uint32_t nxboot_main(void) {
nxboot_move_bootconfig(); nxboot_move_bootconfig();
/* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == ATMOSPHERE_TARGET_FIRMWARE_300) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader;
if (!strcmp(package1loader_header->build_timestamp, "20170519101410")) if (!strcmp(package1loader_header->build_timestamp, "20170519101410"))
pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/ pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/

View file

@ -35,7 +35,7 @@ typedef struct {
#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00 #define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00
#define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000 #define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620)) #define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620))
#define MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + n) #define MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + n)
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10) #define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10)

View file

@ -37,7 +37,7 @@ void nxboot_finish(uint32_t boot_memaddr) {
/* Lock keyslots. */ /* Lock keyslots. */
set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF);
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF);
} else { } else {
set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF);
@ -63,7 +63,7 @@ void nxboot_finish(uint32_t boot_memaddr) {
/* Boot up Exosphère. */ /* Boot up Exosphère. */
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) = 0; MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) = 0;
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_LOADED_PACKAGE2;
} else { } else {
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
@ -94,7 +94,7 @@ void nxboot_finish(uint32_t boot_memaddr) {
} }
/* Signal Exosphère. */ /* Signal Exosphère. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED; MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED;
} else { } else {
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED_4X; MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED_4X;

View file

@ -24,8 +24,10 @@
#include "gpt.h" #include "gpt.h"
#include "se.h" #include "se.h"
#include "utils.h" #include "utils.h"
#include "fs_utils.h"
#include "sdmmc/sdmmc.h" #include "sdmmc/sdmmc.h"
#include "lib/log.h"
#include "lib/fatfs/ff.h" #include "lib/fatfs/ff.h"
static bool g_ahb_redirect_enabled = false; static bool g_ahb_redirect_enabled = false;
@ -227,7 +229,7 @@ static int nxfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector,
case DevicePartitionCryptoMode_Xts: case DevicePartitionCryptoMode_Xts:
set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10); set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10);
set_aes_keyslot(keyslot_b, devpart->keys[1], 0x10); set_aes_keyslot(keyslot_b, devpart->keys[1], 0x10);
se_aes_128_xts_nintendo_decrypt(keyslot_a, keyslot_b, sector, devpart->crypto_work_buffer, devpart->crypto_work_buffer, size, devpart->sector_size); se_aes_128_xts_nintendo_decrypt(keyslot_a, keyslot_b, sector, devpart->crypto_work_buffer, devpart->crypto_work_buffer, size, devpart->sector_size, devpart->crypto_sector_size);
return 0; return 0;
case DevicePartitionCryptoMode_None: case DevicePartitionCryptoMode_None:
default: default:
@ -247,7 +249,7 @@ static int nxfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sector,
case DevicePartitionCryptoMode_Xts: case DevicePartitionCryptoMode_Xts:
set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10); set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10);
set_aes_keyslot(keyslot_b, devpart->keys[1], 0x10); set_aes_keyslot(keyslot_b, devpart->keys[1], 0x10);
se_aes_128_xts_nintendo_encrypt(keyslot_a, keyslot_b, sector, devpart->crypto_work_buffer, devpart->crypto_work_buffer, size, devpart->sector_size); se_aes_128_xts_nintendo_encrypt(keyslot_a, keyslot_b, sector, devpart->crypto_work_buffer, devpart->crypto_work_buffer, size, devpart->sector_size, devpart->crypto_sector_size);
return 0; return 0;
case DevicePartitionCryptoMode_None: case DevicePartitionCryptoMode_None:
default: default:
@ -256,6 +258,7 @@ static int nxfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sector,
} }
static const device_partition_t g_mmc_devpart_template = { static const device_partition_t g_mmc_devpart_template = {
.crypto_sector_size = 0x4000,
.sector_size = 512, .sector_size = 512,
.initializer = mmc_partition_initialize, .initializer = mmc_partition_initialize,
.finalizer = mmc_partition_finalize, .finalizer = mmc_partition_finalize,
@ -264,6 +267,7 @@ static const device_partition_t g_mmc_devpart_template = {
}; };
static const device_partition_t g_emummc_devpart_template = { static const device_partition_t g_emummc_devpart_template = {
.crypto_sector_size = 0x4000,
.sector_size = 512, .sector_size = 512,
.initializer = emummc_partition_initialize, .initializer = emummc_partition_initialize,
.finalizer = emummc_partition_finalize, .finalizer = emummc_partition_finalize,
@ -378,7 +382,7 @@ static int nxfs_mount_emu_partition_gpt_callback(const efi_entry_t *entry, void
{"BCPKG2-5-Repair-Main", "bcpkg25", false, false, false}, {"BCPKG2-5-Repair-Main", "bcpkg25", false, false, false},
{"BCPKG2-6-Repair-Sub", "bcpkg26", false, false, false}, {"BCPKG2-6-Repair-Sub", "bcpkg26", false, false, false},
{"SAFE", "safe", true, true, false}, {"SAFE", "safe", true, true, false},
{"SYSTEM", "system", true, true, false}, {"SYSTEM", "system", true, true, true},
{"USER", "user", true, true, false}, {"USER", "user", true, true, false},
}; };

View file

@ -90,13 +90,13 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
package2_patch_kernel(kernel, &kernel_size, is_sd_kernel, (void *)&orig_ini1, target_firmware); package2_patch_kernel(kernel, &kernel_size, is_sd_kernel, (void *)&orig_ini1, target_firmware);
/* Ensure we know where embedded INI is if present, and we don't if not. */ /* Ensure we know where embedded INI is if present, and we don't if not. */
if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 != NULL) || if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_8_0_0 && orig_ini1 != NULL) ||
(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 == NULL)) { (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0 && orig_ini1 == NULL)) {
fatal_error("Error: inappropriate kernel embedded ini context"); fatal_error("Error: inappropriate kernel embedded ini context");
} }
print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n");
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1); package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
} else { } else {
/* On 8.0.0, place INI1 right after kernelldr for our sanity. */ /* On 8.0.0, place INI1 right after kernelldr for our sanity. */

View file

@ -444,14 +444,24 @@ void aes_128_xts_nintendo_get_tweak(uint8_t *tweak, size_t sector) {
} }
} }
void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, uint8_t *dst, const uint8_t *src, size_t size) { void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, uint8_t *dst, const uint8_t *src, size_t size, size_t crypto_sector_size) {
if ((size & 0xF) || size == 0) { if ((size & 0xF) || size == 0) {
generic_panic(); generic_panic();
} }
unsigned int sector_scale = crypto_sector_size / size;
unsigned int real_sector = sector / sector_scale;
uint8_t tweak[0x10]; uint8_t tweak[0x10];
aes_128_xts_nintendo_get_tweak(tweak, sector); aes_128_xts_nintendo_get_tweak(tweak, real_sector);
se_aes_128_ecb_encrypt_block(keyslot, tweak, sizeof(tweak), tweak, sizeof(tweak)); se_aes_128_ecb_encrypt_block(keyslot, tweak, sizeof(tweak), tweak, sizeof(tweak));
unsigned int num_pre_blocks = ((sector % sector_scale) * size) / 0x10;
for (unsigned int pre = 0; pre < num_pre_blocks; pre++) {
shift_left_xor_rb_le(tweak);
}
for (unsigned int block = 0; block < (size >> 4); block++) { for (unsigned int block = 0; block < (size >> 4); block++) {
for (unsigned int i = 0; i < 0x10; i++) { for (unsigned int i = 0; i < 0x10; i++) {
dst[(block << 4) | i] = src[(block << 4) | i] ^ tweak[i]; dst[(block << 4) | i] = src[(block << 4) | i] ^ tweak[i];
@ -460,15 +470,15 @@ void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, ui
} }
} }
void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size) { void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size, size_t crypto_sector_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if ((size & 0xF) || size == 0) { if ((size & 0xF) || size == 0 || crypto_sector_size < size || (crypto_sector_size % size) != 0) {
generic_panic(); generic_panic();
} }
/* XOR. */ /* XOR. */
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, src, size); aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, src, size, crypto_sector_size);
/* Encrypt/Decrypt. */ /* Encrypt/Decrypt. */
if (encrypt) { if (encrypt) {
@ -482,29 +492,30 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys
trigger_se_blocking_op(OP_START, dst, size, src, size); trigger_se_blocking_op(OP_START, dst, size, src, size);
/* XOR. */ /* XOR. */
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size); aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size, crypto_sector_size);
} }
/* Encrypt with AES-XTS (Nintendo's custom tweak). */ /* Encrypt with AES-XTS (Nintendo's custom tweak). */
void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) { void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size, unsigned int crypto_sector_size) {
if ((size & 0xF) || size == 0) { if ((size & 0xF) || size == 0 || crypto_sector_size < sector_size || (crypto_sector_size % sector_size) != 0) {
generic_panic(); generic_panic();
} }
size_t sector = base_sector; size_t sector = base_sector;
for (size_t ofs = 0; ofs < size; ofs += sector_size) { for (size_t ofs = 0; ofs < size; ofs += sector_size) {
aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, true, dst + ofs, src + ofs, sector_size); aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, true, dst + ofs, src + ofs, sector_size, crypto_sector_size);
sector++; sector++;
} }
} }
/* Decrypt with AES-XTS (Nintendo's custom tweak). */ /* Decrypt with AES-XTS (Nintendo's custom tweak). */
void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) { void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size, unsigned int crypto_sector_size) {
if ((size & 0xF) || size == 0) { if ((size & 0xF) || size == 0 || crypto_sector_size < sector_size || (crypto_sector_size % sector_size) != 0) {
generic_panic(); generic_panic();
} }
size_t sector = base_sector; size_t sector = base_sector;
for (size_t ofs = 0; ofs < size; ofs += sector_size) { for (size_t ofs = 0; ofs < size; ofs += sector_size) {
aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, false, dst + ofs, src + ofs, sector_size); aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, false, dst + ofs, src + ofs, sector_size, crypto_sector_size);
sector++; sector++;
} }
} }

View file

@ -182,8 +182,8 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size);
void set_se_ctr(const void *ctr); void set_se_ctr(const void *ctr);
/* Secure AES API */ /* Secure AES API */
void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size, unsigned int crypto_sector_size);
void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size, unsigned int crypto_sector_size);
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);

View file

@ -676,7 +676,7 @@ namespace ams::kern::arch::arm64::init {
} }
ALWAYS_INLINE void InitializeFromState(uintptr_t state_val) { ALWAYS_INLINE void InitializeFromState(uintptr_t state_val) {
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) { if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
this->state = *reinterpret_cast<State *>(state_val); this->state = *reinterpret_cast<State *>(state_val);
} else { } else {
this->state.next_address = state_val; this->state.next_address = state_val;

View file

@ -20,23 +20,7 @@ namespace ams::kern {
constexpr size_t PageSize = 4_KB; constexpr size_t PageSize = 4_KB;
enum TargetFirmware : u32 { ams::TargetFirmware GetTargetFirmware();
TargetFirmware_1_0_0 = ATMOSPHERE_TARGET_FIRMWARE_100,
TargetFirmware_2_0_0 = ATMOSPHERE_TARGET_FIRMWARE_200,
TargetFirmware_3_0_0 = ATMOSPHERE_TARGET_FIRMWARE_300,
TargetFirmware_4_0_0 = ATMOSPHERE_TARGET_FIRMWARE_400,
TargetFirmware_5_0_0 = ATMOSPHERE_TARGET_FIRMWARE_500,
TargetFirmware_6_0_0 = ATMOSPHERE_TARGET_FIRMWARE_600,
TargetFirmware_6_2_0 = ATMOSPHERE_TARGET_FIRMWARE_620,
TargetFirmware_7_0_0 = ATMOSPHERE_TARGET_FIRMWARE_700,
TargetFirmware_8_0_0 = ATMOSPHERE_TARGET_FIRMWARE_800,
TargetFirmware_8_1_0 = ATMOSPHERE_TARGET_FIRMWARE_810,
TargetFirmware_9_0_0 = ATMOSPHERE_TARGET_FIRMWARE_900,
TargetFirmware_9_1_0 = ATMOSPHERE_TARGET_FIRMWARE_910,
TargetFirmware_10_0_0 = ATMOSPHERE_TARGET_FIRMWARE_1000,
};
TargetFirmware GetTargetFirmware();
} }

View file

@ -21,32 +21,16 @@
namespace ams::exosphere { namespace ams::exosphere {
#define AMS_DEFINE_TARGET_FIRMWARE_ENUM(n) TargetFirmware_##n = ATMOSPHERE_TARGET_FIRMWARE_##n using TargetFirmware = ams::TargetFirmware;
enum TargetFirmware : u32 {
AMS_DEFINE_TARGET_FIRMWARE_ENUM(100),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(200),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(300),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(400),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(500),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(600),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(620),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(700),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(800),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(810),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(900),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(910),
AMS_DEFINE_TARGET_FIRMWARE_ENUM(1000),
};
#undef AMS_DEFINE_TARGET_FIRMWARE_ENUM
constexpr ALWAYS_INLINE u32 GetVersion(u32 major, u32 minor, u32 micro) { constexpr ALWAYS_INLINE u32 GetVersion(u32 major, u32 minor, u32 micro) {
return (major << 16) | (minor << 8) | (micro); return (major << 16) | (minor << 8) | (micro);
} }
struct ApiInfo { struct ApiInfo {
using MasterKeyRevision = util::BitPack64::Field<0, 8, u32>; using TargetFirmwareVersion = util::BitPack64::Field<0, 32, TargetFirmware>;
using TargetFirmwareVersion = util::BitPack64::Field<MasterKeyRevision::Next, 8, TargetFirmware>; using MasterKeyRevision = util::BitPack64::Field<TargetFirmwareVersion::Next, 8, u32>;
using MicroVersion = util::BitPack64::Field<TargetFirmwareVersion::Next, 8, u32>; using MicroVersion = util::BitPack64::Field<MasterKeyRevision::Next, 8, u32>;
using MinorVersion = util::BitPack64::Field<MicroVersion::Next, 8, u32>; using MinorVersion = util::BitPack64::Field<MicroVersion::Next, 8, u32>;
using MajorVersion = util::BitPack64::Field<MinorVersion::Next, 8, u32>; using MajorVersion = util::BitPack64::Field<MinorVersion::Next, 8, u32>;

View file

@ -19,22 +19,47 @@
namespace ams::hos { namespace ams::hos {
enum Version : u16 { enum Version : u32 {
Version_Min = 0, Version_Min = ::ams::TargetFirmware_Min,
Version_1_0_0 = Version_Min,
Version_2_0_0 = 1, Version_1_0_0 = ::ams::TargetFirmware_1_0_0,
Version_3_0_0 = 2, Version_2_0_0 = ::ams::TargetFirmware_2_0_0,
Version_4_0_0 = 3, Version_2_1_0 = ::ams::TargetFirmware_2_1_0,
Version_5_0_0 = 4, Version_2_2_0 = ::ams::TargetFirmware_2_2_0,
Version_6_0_0 = 5, Version_2_3_0 = ::ams::TargetFirmware_2_3_0,
Version_7_0_0 = 6, Version_3_0_0 = ::ams::TargetFirmware_3_0_0,
Version_8_0_0 = 7, Version_3_0_1 = ::ams::TargetFirmware_3_0_1,
Version_8_1_0 = 8, Version_3_0_2 = ::ams::TargetFirmware_3_0_2,
Version_9_0_0 = 9, Version_4_0_0 = ::ams::TargetFirmware_4_0_0,
Version_9_1_0 = 10, Version_4_0_1 = ::ams::TargetFirmware_4_0_1,
Version_10_0_0 = 11, Version_4_1_0 = ::ams::TargetFirmware_4_1_0,
Version_Current = Version_10_0_0, Version_5_0_0 = ::ams::TargetFirmware_5_0_0,
Version_Max = 32, Version_5_0_1 = ::ams::TargetFirmware_5_0_1,
Version_5_0_2 = ::ams::TargetFirmware_5_0_2,
Version_5_1_0 = ::ams::TargetFirmware_5_1_0,
Version_6_0_0 = ::ams::TargetFirmware_6_0_0,
Version_6_0_1 = ::ams::TargetFirmware_6_0_1,
Version_6_1_0 = ::ams::TargetFirmware_6_1_0,
Version_6_2_0 = ::ams::TargetFirmware_6_2_0,
Version_7_0_0 = ::ams::TargetFirmware_7_0_0,
Version_7_0_1 = ::ams::TargetFirmware_7_0_1,
Version_8_0_0 = ::ams::TargetFirmware_8_0_0,
Version_8_0_1 = ::ams::TargetFirmware_8_0_1,
Version_8_1_0 = ::ams::TargetFirmware_8_1_0,
Version_8_1_1 = ::ams::TargetFirmware_8_1_1,
Version_9_0_0 = ::ams::TargetFirmware_9_0_0,
Version_9_0_1 = ::ams::TargetFirmware_9_0_1,
Version_9_1_0 = ::ams::TargetFirmware_9_1_0,
Version_9_2_0 = ::ams::TargetFirmware_9_2_0,
Version_10_0_0 = ::ams::TargetFirmware_10_0_0,
Version_10_0_1 = ::ams::TargetFirmware_10_0_1,
Version_10_0_2 = ::ams::TargetFirmware_10_0_2,
Version_Current = ::ams::TargetFirmware_Current,
Version_Max = ::ams::TargetFirmware_Max,
}; };
} }

View file

@ -61,7 +61,7 @@ namespace ams::sf::cmif {
return this->handler; return this->handler;
} }
}; };
static_assert(std::is_pod<ServiceCommandMeta>::value && sizeof(ServiceCommandMeta) == 0x10, "sizeof(ServiceCommandMeta)"); static_assert(std::is_pod<ServiceCommandMeta>::value && sizeof(ServiceCommandMeta) == 0x18, "sizeof(ServiceCommandMeta)");
namespace impl { namespace impl {

View file

@ -35,46 +35,9 @@ namespace ams::hos {
return; return;
} }
switch (exosphere::GetApiInfo().GetTargetFirmware()) { /* Hos version is a direct copy of target firmware, just renamed. */
case exosphere::TargetFirmware_100: g_hos_version = static_cast<hos::Version>(exosphere::GetApiInfo().GetTargetFirmware());
g_hos_version = hos::Version_1_0_0; AMS_ABORT_UNLESS(g_hos_version <= hos::Version_Max);
break;
case exosphere::TargetFirmware_200:
g_hos_version = hos::Version_2_0_0;
break;
case exosphere::TargetFirmware_300:
g_hos_version = hos::Version_3_0_0;
break;
case exosphere::TargetFirmware_400:
g_hos_version = hos::Version_4_0_0;
break;
case exosphere::TargetFirmware_500:
g_hos_version = hos::Version_5_0_0;
break;
case exosphere::TargetFirmware_600:
case exosphere::TargetFirmware_620:
g_hos_version = hos::Version_6_0_0;
break;
case exosphere::TargetFirmware_700:
g_hos_version = hos::Version_7_0_0;
break;
case exosphere::TargetFirmware_800:
g_hos_version = hos::Version_8_0_0;
break;
case exosphere::TargetFirmware_810:
g_hos_version = hos::Version_8_1_0;
break;
case exosphere::TargetFirmware_900:
g_hos_version = hos::Version_9_0_0;
break;
case exosphere::TargetFirmware_910:
g_hos_version = hos::Version_9_1_0;
break;
case exosphere::TargetFirmware_1000:
g_hos_version = hos::Version_10_0_0;
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
__atomic_store_n(&g_has_cached, true, __ATOMIC_SEQ_CST); __atomic_store_n(&g_has_cached, true, __ATOMIC_SEQ_CST);
} }
@ -87,69 +50,10 @@ namespace ams::hos {
} }
void SetVersionForLibnxInternal() { void SetVersionForLibnxInternal() {
u32 major = 0, minor = 0, micro = 0; const u32 hos_version_val = static_cast<u32>(hos::GetVersion());
switch (hos::GetVersion()) { const u32 major = (hos_version_val >> 24) & 0xFF;
case hos::Version_1_0_0: const u32 minor = (hos_version_val >> 16) & 0xFF;
major = 1; const u32 micro = (hos_version_val >> 8) & 0xFF;
minor = 0;
micro = 0;
break;
case hos::Version_2_0_0:
major = 2;
minor = 0;
micro = 0;
break;
case hos::Version_3_0_0:
major = 3;
minor = 0;
micro = 0;
break;
case hos::Version_4_0_0:
major = 4;
minor = 0;
micro = 0;
break;
case hos::Version_5_0_0:
major = 5;
minor = 0;
micro = 0;
break;
case hos::Version_6_0_0:
major = 6;
minor = 0;
micro = 0;
break;
case hos::Version_7_0_0:
major = 7;
minor = 0;
micro = 0;
break;
case hos::Version_8_0_0:
major = 8;
minor = 0;
micro = 0;
break;
case hos::Version_8_1_0:
major = 8;
minor = 1;
micro = 0;
break;
case hos::Version_9_0_0:
major = 9;
minor = 0;
micro = 0;
case hos::Version_9_1_0:
major = 9;
minor = 1;
micro = 0;
break;
case hos::Version_10_0_0:
major = 10;
minor = 0;
micro = 0;
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
hosversionSet(MAKEHOSVERSION(major, minor, micro)); hosversionSet(MAKEHOSVERSION(major, minor, micro));
} }

View file

@ -15,22 +15,94 @@
*/ */
#pragma once #pragma once
#define ATMOSPHERE_TARGET_FIRMWARE_100 1 #define ATMOSPHERE_TARGET_FIRMWARE_WITH_REVISION(major, minor, micro, rev) ((major << 24) | (minor << 16) | (micro << 8) | (rev))
#define ATMOSPHERE_TARGET_FIRMWARE_200 2
#define ATMOSPHERE_TARGET_FIRMWARE_300 3
#define ATMOSPHERE_TARGET_FIRMWARE_400 4
#define ATMOSPHERE_TARGET_FIRMWARE_500 5
#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_810 10
#define ATMOSPHERE_TARGET_FIRMWARE_900 11
#define ATMOSPHERE_TARGET_FIRMWARE_910 12
#define ATMOSPHERE_TARGET_FIRMWARE_1000 13
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_1000 #define ATMOSPHERE_TARGET_FIRMWARE(major, minor, micro) ATMOSPHERE_TARGET_FIRMWARE_WITH_REVISION(major, minor, micro, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100 #define ATMOSPHERE_TARGET_FIRMWARE_1_0_0 ATMOSPHERE_TARGET_FIRMWARE( 1, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_2_0_0 ATMOSPHERE_TARGET_FIRMWARE( 2, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_2_1_0 ATMOSPHERE_TARGET_FIRMWARE( 2, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_2_2_0 ATMOSPHERE_TARGET_FIRMWARE( 2, 2, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_2_3_0 ATMOSPHERE_TARGET_FIRMWARE( 2, 3, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_3_0_0 ATMOSPHERE_TARGET_FIRMWARE( 3, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_3_0_1 ATMOSPHERE_TARGET_FIRMWARE( 3, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_3_0_2 ATMOSPHERE_TARGET_FIRMWARE( 3, 0, 2)
#define ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ATMOSPHERE_TARGET_FIRMWARE( 4, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_4_0_1 ATMOSPHERE_TARGET_FIRMWARE( 4, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_4_1_0 ATMOSPHERE_TARGET_FIRMWARE( 4, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ATMOSPHERE_TARGET_FIRMWARE( 5, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_5_0_1 ATMOSPHERE_TARGET_FIRMWARE( 5, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_5_0_2 ATMOSPHERE_TARGET_FIRMWARE( 5, 0, 2)
#define ATMOSPHERE_TARGET_FIRMWARE_5_1_0 ATMOSPHERE_TARGET_FIRMWARE( 5, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_6_0_0 ATMOSPHERE_TARGET_FIRMWARE( 6, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_6_0_1 ATMOSPHERE_TARGET_FIRMWARE( 6, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_6_1_0 ATMOSPHERE_TARGET_FIRMWARE( 6, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_6_2_0 ATMOSPHERE_TARGET_FIRMWARE( 6, 2, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_7_0_0 ATMOSPHERE_TARGET_FIRMWARE( 7, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_7_0_1 ATMOSPHERE_TARGET_FIRMWARE( 7, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_8_0_0 ATMOSPHERE_TARGET_FIRMWARE( 8, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_8_0_1 ATMOSPHERE_TARGET_FIRMWARE( 8, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_8_1_0 ATMOSPHERE_TARGET_FIRMWARE( 8, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_8_1_1 ATMOSPHERE_TARGET_FIRMWARE( 8, 1, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_9_0_0 ATMOSPHERE_TARGET_FIRMWARE( 9, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_9_0_1 ATMOSPHERE_TARGET_FIRMWARE( 9, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_9_1_0 ATMOSPHERE_TARGET_FIRMWARE( 9, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_9_2_0 ATMOSPHERE_TARGET_FIRMWARE( 9, 2, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_10_0_0 ATMOSPHERE_TARGET_FIRMWARE(10, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_10_0_1 ATMOSPHERE_TARGET_FIRMWARE(10, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_10_0_2 ATMOSPHERE_TARGET_FIRMWARE(10, 0, 2)
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_10_0_2
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
#define ATMOSPHERE_TARGET_FIRMWARE_COUNT ((ATMOSPHERE_TARGET_FIRMWARE_MAX - ATMOSPHERE_TARGET_FIRMWARE_MIN) + 1)
#ifdef __cplusplus
namespace ams {
enum TargetFirmware : u32 {
TargetFirmware_Min = ATMOSPHERE_TARGET_FIRMWARE_MIN,
TargetFirmware_1_0_0 = ATMOSPHERE_TARGET_FIRMWARE_1_0_0,
TargetFirmware_2_0_0 = ATMOSPHERE_TARGET_FIRMWARE_2_0_0,
TargetFirmware_2_1_0 = ATMOSPHERE_TARGET_FIRMWARE_2_1_0,
TargetFirmware_2_2_0 = ATMOSPHERE_TARGET_FIRMWARE_2_2_0,
TargetFirmware_2_3_0 = ATMOSPHERE_TARGET_FIRMWARE_2_3_0,
TargetFirmware_3_0_0 = ATMOSPHERE_TARGET_FIRMWARE_3_0_0,
TargetFirmware_3_0_1 = ATMOSPHERE_TARGET_FIRMWARE_3_0_1,
TargetFirmware_3_0_2 = ATMOSPHERE_TARGET_FIRMWARE_3_0_2,
TargetFirmware_4_0_0 = ATMOSPHERE_TARGET_FIRMWARE_4_0_0,
TargetFirmware_4_0_1 = ATMOSPHERE_TARGET_FIRMWARE_4_0_1,
TargetFirmware_4_1_0 = ATMOSPHERE_TARGET_FIRMWARE_4_1_0,
TargetFirmware_5_0_0 = ATMOSPHERE_TARGET_FIRMWARE_5_0_0,
TargetFirmware_5_0_1 = ATMOSPHERE_TARGET_FIRMWARE_5_0_1,
TargetFirmware_5_0_2 = ATMOSPHERE_TARGET_FIRMWARE_5_0_2,
TargetFirmware_5_1_0 = ATMOSPHERE_TARGET_FIRMWARE_5_1_0,
TargetFirmware_6_0_0 = ATMOSPHERE_TARGET_FIRMWARE_6_0_0,
TargetFirmware_6_0_1 = ATMOSPHERE_TARGET_FIRMWARE_6_0_1,
TargetFirmware_6_1_0 = ATMOSPHERE_TARGET_FIRMWARE_6_1_0,
TargetFirmware_6_2_0 = ATMOSPHERE_TARGET_FIRMWARE_6_2_0,
TargetFirmware_7_0_0 = ATMOSPHERE_TARGET_FIRMWARE_7_0_0,
TargetFirmware_7_0_1 = ATMOSPHERE_TARGET_FIRMWARE_7_0_1,
TargetFirmware_8_0_0 = ATMOSPHERE_TARGET_FIRMWARE_8_0_0,
TargetFirmware_8_0_1 = ATMOSPHERE_TARGET_FIRMWARE_8_0_1,
TargetFirmware_8_1_0 = ATMOSPHERE_TARGET_FIRMWARE_8_1_0,
TargetFirmware_8_1_1 = ATMOSPHERE_TARGET_FIRMWARE_8_1_1,
TargetFirmware_9_0_0 = ATMOSPHERE_TARGET_FIRMWARE_9_0_0,
TargetFirmware_9_0_1 = ATMOSPHERE_TARGET_FIRMWARE_9_0_1,
TargetFirmware_9_1_0 = ATMOSPHERE_TARGET_FIRMWARE_9_1_0,
TargetFirmware_9_2_0 = ATMOSPHERE_TARGET_FIRMWARE_9_2_0,
TargetFirmware_10_0_0 = ATMOSPHERE_TARGET_FIRMWARE_10_0_0,
TargetFirmware_10_0_1 = ATMOSPHERE_TARGET_FIRMWARE_10_0_1,
TargetFirmware_10_0_2 = ATMOSPHERE_TARGET_FIRMWARE_10_0_2,
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,
TargetFirmware_Max = ATMOSPHERE_TARGET_FIRMWARE_MAX,
};
static_assert(TargetFirmware_Current <= TargetFirmware_Max);
}
#endif

View file

@ -50,7 +50,7 @@ namespace ams::kern::init {
static_assert(KernelResourceRegionSize + ExtraKernelResourceSize > InitialProcessBinarySizeMax); static_assert(KernelResourceRegionSize + ExtraKernelResourceSize > InitialProcessBinarySizeMax);
/* 10.0.0 reduced the kernel resource region size by 64K. */ /* 10.0.0 reduced the kernel resource region size by 64K. */
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) { if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
resource_region_size -= KernelResourceReduction_10_0_0; resource_region_size -= KernelResourceReduction_10_0_0;
} }
return resource_region_size; return resource_region_size;

View file

@ -48,7 +48,7 @@ namespace ams::kern::init::loader {
static_assert(KernelResourceRegionSize + ExtraKernelResourceSize > InitialProcessBinarySizeMax); static_assert(KernelResourceRegionSize + ExtraKernelResourceSize > InitialProcessBinarySizeMax);
/* 10.0.0 reduced the kernel resource region size by 64K. */ /* 10.0.0 reduced the kernel resource region size by 64K. */
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) { if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
resource_region_size -= KernelResourceReduction_10_0_0; resource_region_size -= KernelResourceReduction_10_0_0;
} }
return resource_region_size; return resource_region_size;
@ -118,7 +118,7 @@ namespace ams::kern::init::loader {
cpu::TranslationControlRegisterAccessor(TcrValue).Store(); cpu::TranslationControlRegisterAccessor(TcrValue).Store();
/* Perform cpu-specific setup on < 10.0.0. */ /* Perform cpu-specific setup on < 10.0.0. */
if (kern::GetTargetFirmware() < kern::TargetFirmware_10_0_0) { if (kern::GetTargetFirmware() < ams::TargetFirmware_10_0_0) {
SavedRegisterState saved_registers; SavedRegisterState saved_registers;
SaveRegistersToTpidrEl1(&saved_registers); SaveRegistersToTpidrEl1(&saved_registers);
ON_SCOPE_EXIT { VerifyAndClearTpidrEl1(&saved_registers); }; ON_SCOPE_EXIT { VerifyAndClearTpidrEl1(&saved_registers); };
@ -305,7 +305,7 @@ namespace ams::kern::init::loader {
ttbr1_table.Map(virtual_base_address + rw_offset, bss_end_offset - rw_offset, base_address + rw_offset, KernelRwDataAttribute, g_initial_page_allocator); ttbr1_table.Map(virtual_base_address + rw_offset, bss_end_offset - rw_offset, base_address + rw_offset, KernelRwDataAttribute, g_initial_page_allocator);
/* On 10.0.0+, Physically randomize the kernel region. */ /* On 10.0.0+, Physically randomize the kernel region. */
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) { if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true); ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true);
cpu::StoreEntireCacheForInit(); cpu::StoreEntireCacheForInit();
} }
@ -333,7 +333,7 @@ namespace ams::kern::init::loader {
uintptr_t GetFinalPageAllocatorState() { uintptr_t GetFinalPageAllocatorState() {
g_initial_page_allocator.GetFinalState(std::addressof(g_final_page_allocator_state)); g_initial_page_allocator.GetFinalState(std::addressof(g_final_page_allocator_state));
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) { if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
return reinterpret_cast<uintptr_t>(std::addressof(g_final_page_allocator_state)); return reinterpret_cast<uintptr_t>(std::addressof(g_final_page_allocator_state));
} else { } else {
return g_final_page_allocator_state.next_address; return g_final_page_allocator_state.next_address;

View file

@ -204,7 +204,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1)); uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
/* Firmware from versions 1.0.0 to 3.0.2. */ /* Firmware from versions 1.0.0 to 3.0.2. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
if (hardware_type >= 1) { if (hardware_type >= 1) {
return (hardware_type > 2) ? 3 : hardware_type - 1; return (hardware_type > 2) ? 3 : hardware_type - 1;
@ -213,7 +213,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
} else { } else {
return 3; return 3;
} }
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */ } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* Firmware versions from 4.0.0 to 6.2.0. */
static const uint32_t types[] = {0,1,4,3}; static const uint32_t types[] = {0,1,4,3};
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C); hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
hardware_type--; hardware_type--;

View file

@ -206,7 +206,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1)); uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
/* Firmware from versions 1.0.0 to 3.0.2. */ /* Firmware from versions 1.0.0 to 3.0.2. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
if (hardware_type >= 1) { if (hardware_type >= 1) {
return (hardware_type > 2) ? 3 : hardware_type - 1; return (hardware_type > 2) ? 3 : hardware_type - 1;
@ -215,7 +215,7 @@ uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
} else { } else {
return 3; return 3;
} }
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */ } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* Firmware versions from 4.0.0 to 6.2.0. */
static const uint32_t types[] = {0,1,4,3}; static const uint32_t types[] = {0,1,4,3};
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C); hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
hardware_type--; hardware_type--;