mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
ams: revamp target firmware
This commit is contained in:
parent
85cd2c97a0
commit
8e75a4169d
48 changed files with 863 additions and 693 deletions
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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+) */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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--;
|
||||||
|
|
|
@ -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--;
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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.*/
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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--;
|
||||||
|
|
|
@ -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--;
|
||||||
|
|
Loading…
Reference in a new issue