ams: revamp target firmware

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "utils.h" #include "utils.h"
#include "lp0.h" #include "lp0.h"
#include "mc.h" #include "mc.h"
@ -41,56 +41,56 @@ void lp0_entry_main(warmboot_metadata_t *meta) {
if (meta->magic != WARMBOOT_MAGIC || target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX) { if (meta->magic != WARMBOOT_MAGIC || target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX) {
reboot(); reboot();
} }
/* [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();
} }
/* Configure debugging depending on FUSE_PRODUCTION_MODE */ /* Configure debugging depending on FUSE_PRODUCTION_MODE */
misc_configure_device_dbg_settings(); misc_configure_device_dbg_settings();
/* Check for downgrade. */ /* Check for downgrade. */
/* NOTE: We implemented this as "return false" */ /* NOTE: We implemented this as "return false" */
if (fuse_check_downgrade_status()) { if (fuse_check_downgrade_status()) {
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 */) {
reboot(); reboot();
} }
} }
/* TODO: Check that we're running at the correct physical address. */ /* TODO: Check that we're running at the correct physical address. */
/* Setup fuses, disable bypass. */ /* Setup fuses, disable bypass. */
fuse_configure_fuse_bypass(); fuse_configure_fuse_bypass();
/* Configure oscillators/timing in CAR. */ /* Configure oscillators/timing in CAR. */
car_configure_oscillators(); car_configure_oscillators();
/* Restore RAM configuration. */ /* Restore RAM configuration. */
misc_restore_ram_svop(); misc_restore_ram_svop();
emc_configure_pmacro_training(); emc_configure_pmacro_training();
/* Setup clock output for all devices, working around mbist bug. */ /* Setup clock output for all devices, working around mbist bug. */
car_mbist_workaround(); car_mbist_workaround();
/* Initialize the CPU cluster. */ /* Initialize the CPU cluster. */
cluster_initialize_cpu(); cluster_initialize_cpu();
secmon_restore_to_tzram(target_firmware); secmon_restore_to_tzram(target_firmware);
/* Power on the CPU cluster. */ /* Power on the CPU cluster. */
cluster_power_on_cpu(); cluster_power_on_cpu();
/* Nintendo clears most of warmboot.bin out of IRAM here. We're not gonna bother. */ /* Nintendo clears most of warmboot.bin out of IRAM here. We're not gonna bother. */
/* memset( ... ); */ /* memset( ... ); */
const uint32_t halt_val = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x40000000 : 0x50000000; const uint32_t halt_val = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ? 0x40000000 : 0x50000000;
while (true) { while (true) {
/* Halt the BPMP. */ /* Halt the BPMP. */
FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val; FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val;

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>
#include "utils.h" #include "utils.h"
@ -30,13 +30,13 @@ static void secmon_decrypt_saved_image(void *dst, const void *src, size_t size);
void secmon_restore_to_tzram(const uint32_t target_firmware) { void secmon_restore_to_tzram(const uint32_t target_firmware) {
/* Newer warmboot binaries clear the untouched keyslots for safety. */ /* Newer warmboot binaries clear the untouched keyslots for safety. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
secmon_clear_unused_keyslots(); secmon_clear_unused_keyslots();
} }
/* Decrypt Secure Monitor from DRAM into TZRAM. */ /* Decrypt Secure Monitor from DRAM into TZRAM. */
void *tzram_src = (void *)(0x80010000); void *tzram_src = (void *)(0x80010000);
void *tzram_dst = (void *)(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500 ? 0x7C012000 : 0x7C010000); void *tzram_dst = (void *)(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ? 0x7C012000 : 0x7C010000);
const size_t tzram_size = 0xE000; const size_t tzram_size = 0xE000;
secmon_decrypt_saved_image(tzram_dst, tzram_src, tzram_size); secmon_decrypt_saved_image(tzram_dst, tzram_src, tzram_size);

View file

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h> #include <string.h>
#include "utils.h" #include "utils.h"
#include "arm.h" #include "arm.h"
@ -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[];
@ -52,11 +52,11 @@ static void mmio_map_all_devices(uintptr_t *mmu_l3_tbl, unsigned int target_firm
static const uintptr_t pas[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; static const uintptr_t pas[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) };
static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) };
static const bool is_secure[] = { TUPLE_FOLD_LEFT_2(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; static const bool is_secure[] = { TUPLE_FOLD_LEFT_2(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) };
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;
@ -92,9 +92,9 @@ static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl, unsigned int target_fi
static const bool is_executable[] = { TUPLE_FOLD_LEFT_3(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; static const bool is_executable[] = { TUPLE_FOLD_LEFT_3(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) };
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];
} }
@ -102,9 +102,9 @@ static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl, unsigned int target_fi
static void configure_ttbls(unsigned int target_firmware) { 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,12 +154,12 @@ 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;
} }
} }
void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold) { void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold) {
@ -196,7 +196,7 @@ void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold)
init_dma_controllers(g_exosphere_target_firmware_for_init); init_dma_controllers(g_exosphere_target_firmware_for_init);
configure_ttbls(g_exosphere_target_firmware_for_init); configure_ttbls(g_exosphere_target_firmware_for_init);
if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) { if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
set_memory_registers_enable_mmu_1x_ttbr0(); set_memory_registers_enable_mmu_1x_ttbr0();
} else { } else {
set_memory_registers_enable_mmu_5x_ttbr0(); set_memory_registers_enable_mmu_5x_ttbr0();

View file

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "arm.h" #include "arm.h"
@ -99,8 +99,8 @@ 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,11 +133,11 @@ 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);
} }
return 0; return 0;
} }

View file

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

View file

@ -47,7 +47,7 @@ void configure_gpu_ucode_carveout(void) {
carveout->size_big_pages = 2; /* 0x40000 */ carveout->size_big_pages = 2; /* 0x40000 */
carveout->client_access_0 = 0; carveout->client_access_0 = 0;
carveout->client_access_1 = 0; carveout->client_access_1 = 0;
carveout->client_access_2 = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); carveout->client_access_2 = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR));
carveout->client_access_3 = 0; carveout->client_access_3 = 0;
carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2));
carveout->client_force_internal_access_0 = 0; carveout->client_force_internal_access_0 = 0;
@ -77,7 +77,7 @@ void configure_default_carveouts(void) {
carveout->config = 0x4000006; carveout->config = 0x4000006;
/* Configure Carveout 2 (GPU UCODE) */ /* Configure Carveout 2 (GPU UCODE) */
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_600) { if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_6_0_0) {
configure_gpu_ucode_carveout(); configure_gpu_ucode_carveout();
} }
@ -99,7 +99,7 @@ void configure_default_carveouts(void) {
carveout->config = 0x4401E7E; carveout->config = 0x4401E7E;
/* Configure default Kernel carveouts based on 2.0.0+. */ /* Configure default Kernel carveouts based on 2.0.0+. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) {
/* Configure Carveout 4 (KERNEL_BUILTINS) */ /* Configure Carveout 4 (KERNEL_BUILTINS) */
configure_kernel_carveout(4, g_saved_carveouts[0].address, g_saved_carveouts[0].size); configure_kernel_carveout(4, g_saved_carveouts[0].address, g_saved_carveouts[0].size);
@ -140,11 +140,11 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6
carveout->size_big_pages = (uint32_t)(size >> 17); carveout->size_big_pages = (uint32_t)(size >> 17);
carveout->client_access_0 = (BIT(CSR_PTCR) | BIT(CSR_DISPLAY0A) | BIT(CSR_DISPLAY0AB) | BIT(CSR_DISPLAY0B) | BIT(CSR_DISPLAY0BB) | BIT(CSR_DISPLAY0C) | BIT(CSR_DISPLAY0CB) | BIT(CSR_AFIR) | BIT(CSR_DISPLAYHC) | BIT(CSR_DISPLAYHCB) | BIT(CSR_HDAR) | BIT(CSR_HOST1XDMAR) | BIT(CSR_HOST1XR) | BIT(CSR_NVENCSRD) | BIT(CSR_PPCSAHBDMAR) | BIT(CSR_PPCSAHBSLVR)); carveout->client_access_0 = (BIT(CSR_PTCR) | BIT(CSR_DISPLAY0A) | BIT(CSR_DISPLAY0AB) | BIT(CSR_DISPLAY0B) | BIT(CSR_DISPLAY0BB) | BIT(CSR_DISPLAY0C) | BIT(CSR_DISPLAY0CB) | BIT(CSR_AFIR) | BIT(CSR_DISPLAYHC) | BIT(CSR_DISPLAYHCB) | BIT(CSR_HDAR) | BIT(CSR_HOST1XDMAR) | BIT(CSR_HOST1XR) | BIT(CSR_NVENCSRD) | BIT(CSR_PPCSAHBDMAR) | BIT(CSR_PPCSAHBSLVR));
carveout->client_access_1 = (BIT(CSR_MPCORER) | BIT(CSW_NVENCSWR) | BIT(CSW_AFIW) | BIT(CSW_HDAW) | BIT(CSW_HOST1XW) | BIT(CSW_MPCOREW) | BIT(CSW_PPCSAHBDMAW) | BIT(CSW_PPCSAHBSLVW)); carveout->client_access_1 = (BIT(CSR_MPCORER) | BIT(CSW_NVENCSWR) | BIT(CSW_AFIW) | BIT(CSW_HDAW) | BIT(CSW_HOST1XW) | BIT(CSW_MPCOREW) | BIT(CSW_PPCSAHBDMAW) | BIT(CSW_PPCSAHBSLVW));
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_810) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW)); carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW));
carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR));
carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR)); carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR));
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_800) { } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW)); carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW));
carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR));
carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR) | BIT(CSR_TSECSRDB) | BIT(CSW_TSECSWRB)); carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR) | BIT(CSR_TSECSRDB) | BIT(CSW_TSECSWRB));
@ -153,10 +153,10 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6
carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR));
carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR)); carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR));
} }
carveout->client_force_internal_access_0 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSR_AVPCARM7R) : 0; carveout->client_force_internal_access_0 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) && (carveout_id == 4)) ? BIT(CSR_AVPCARM7R) : 0;
carveout->client_force_internal_access_1 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0; carveout->client_force_internal_access_1 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0;
carveout->client_force_internal_access_2 = 0; carveout->client_force_internal_access_2 = 0;
carveout->client_force_internal_access_3 = 0; carveout->client_force_internal_access_3 = 0;
carveout->client_force_internal_access_4 = 0; carveout->client_force_internal_access_4 = 0;
carveout->config = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_800) ? 0x4CB : 0x8B; carveout->config = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0) ? 0x4CB : 0x8B;
} }

View file

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

View file

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

View file

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -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;
@ -59,7 +59,7 @@ void seal_titlekey(void *dst, size_t dst_size, const void *src, size_t src_size)
if (dst_size != 0x10 || src_size != 0x10) { if (dst_size != 0x10 || src_size != 0x10) {
generic_panic(); generic_panic();
} }
seal_key_internal(dst, src, g_titlekey_seal_key_source); seal_key_internal(dst, src, g_titlekey_seal_key_source);
} }
@ -68,7 +68,7 @@ void unseal_titlekey(unsigned int keyslot, const void *src, size_t src_size) {
if (src_size != 0x10) { if (src_size != 0x10) {
generic_panic(); generic_panic();
} }
unseal_key_internal(keyslot, src, g_titlekey_seal_key_source); unseal_key_internal(keyslot, src, g_titlekey_seal_key_source);
} }
@ -77,8 +77,8 @@ void seal_key(void *dst, size_t dst_size, const void *src, size_t src_size, unsi
if (usecase_is_invalid(usecase) || dst_size != 0x10 || src_size != 0x10) { if (usecase_is_invalid(usecase) || dst_size != 0x10 || src_size != 0x10) {
generic_panic(); generic_panic();
} }
seal_key_internal(dst, src, g_seal_key_sources[usecase]); seal_key_internal(dst, src, g_seal_key_sources[usecase]);
} }
@ -86,6 +86,6 @@ void unseal_key(unsigned int keyslot, const void *src, size_t src_size, unsigned
if (usecase_is_invalid(usecase) || src_size != 0x10) { if (usecase_is_invalid(usecase) || src_size != 0x10) {
generic_panic(); generic_panic();
} }
unseal_key_internal(keyslot, src, g_seal_key_sources[usecase]); unseal_key_internal(keyslot, src, g_seal_key_sources[usecase]);
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "utils.h" #include "utils.h"
#include "mmu.h" #include "mmu.h"
#include "memory_map.h" #include "memory_map.h"
@ -53,7 +53,7 @@ void __attribute__((noreturn)) warmboot_main(void) {
- warmboot (core 3) - warmboot (core 3)
- cpu_on - cpu_on
*/ */
if (is_core_active(get_core_id())) { if (is_core_active(get_core_id())) {
panic(0xF7F00009); /* invalid CPU context */ panic(0xF7F00009); /* invalid CPU context */
} }
@ -70,7 +70,7 @@ void __attribute__((noreturn)) warmboot_main(void) {
clkrst_reboot(CARDEVICE_UARTA); clkrst_reboot(CARDEVICE_UARTA);
uart_init(UART_A, 115200); uart_init(UART_A, 115200);
} }
if (!configitem_is_retail()) { if (!configitem_is_retail()) {
uart_send(UART_A, "OHAYO", 6); uart_send(UART_A, "OHAYO", 6);
uart_wait_idle(UART_A, UART_VENDOR_STATE_TX_IDLE); uart_wait_idle(UART_A, UART_VENDOR_STATE_TX_IDLE);
@ -87,15 +87,15 @@ void __attribute__((noreturn)) warmboot_main(void) {
/* Make PMC (2.x+), MC (4.x+) registers secure-only */ /* Make PMC (2.x+), MC (4.x+) registers secure-only */
secure_additional_devices(); secure_additional_devices();
if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) || if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ||
((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_800) && configitem_get_hardware_type() == 0) || ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) && configitem_get_hardware_type() == 0) ||
(configitem_is_hiz_mode_enabled())) { (configitem_is_hiz_mode_enabled())) {
warmboot_configure_hiz_mode(); warmboot_configure_hiz_mode();
} }
clear_user_smc_in_progress(); clear_user_smc_in_progress();
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
setup_4x_mmio(); setup_4x_mmio();
} }
} }

View file

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

View file

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FUSEE_DEVICE_PARTITION_H #ifndef FUSEE_DEVICE_PARTITION_H
#define FUSEE_DEVICE_PARTITION_H #define FUSEE_DEVICE_PARTITION_H
@ -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. */
@ -65,7 +66,7 @@ typedef struct device_partition_t {
uint8_t __attribute__((aligned(16))) keys[DEVPART_KEY_MAX][DEVPART_KEY_MAX_SIZE]; /* Key. */ uint8_t __attribute__((aligned(16))) keys[DEVPART_KEY_MAX][DEVPART_KEY_MAX_SIZE]; /* Key. */
uint8_t __attribute__((aligned(16))) iv[DEVPART_IV_MAX_SIZE]; /* IV. */ uint8_t __attribute__((aligned(16))) iv[DEVPART_IV_MAX_SIZE]; /* IV. */
bool initialized; bool initialized;
char *emu_file_path; /* Emulated device file path. */ char *emu_file_path; /* Emulated device file path. */
bool emu_use_file; bool emu_use_file;
} device_partition_t; } device_partition_t;

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
@ -121,7 +121,7 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool
fsdev_device_t *device = fsdev_find_device(name); fsdev_device_t *device = fsdev_find_device(name);
FRESULT rc; FRESULT rc;
char drname[40]; char drname[40];
if (device != NULL) { if (device != NULL) {
errno = EEXIST; /* Device already exists */ errno = EEXIST; /* Device already exists */
return -1; return -1;
@ -170,7 +170,7 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool
VolumeStr[device - g_fsdev_devices] = FKNAM; VolumeStr[device - g_fsdev_devices] = FKNAM;
return fsdev_convert_rc(NULL, rc); return fsdev_convert_rc(NULL, rc);
} }
device->setup = true; device->setup = true;
device->registered = false; device->registered = false;
@ -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);
@ -403,7 +417,7 @@ static void fsdev_filinfo_to_st(struct stat *st, const FILINFO *info) {
date.tm_sec = (info->ftime << 1) & 63; date.tm_sec = (info->ftime << 1) & 63;
date.tm_min = (info->ftime >> 5) & 63; date.tm_min = (info->ftime >> 5) & 63;
date.tm_hour = (info->ftime >> 11) & 31; date.tm_hour = (info->ftime >> 11) & 31;
date.tm_isdst = 0; date.tm_isdst = 0;
st->st_atime = st->st_mtime = st->st_ctime = mktime(&date); st->st_atime = st->st_mtime = st->st_ctime = mktime(&date);

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FUSEE_FS_DEV_H #ifndef FUSEE_FS_DEV_H
#define FUSEE_FS_DEV_H #define FUSEE_FS_DEV_H
@ -21,12 +21,15 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "device_partition.h" #include "device_partition.h"
#include "key_derivation.h"
int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately); int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately);
int fsdev_register_device(const char *name); int fsdev_register_device(const char *name);
int fsdev_unregister_device(const char *name); int fsdev_unregister_device(const char *name);
int fsdev_unmount_device(const char *name); /* also unregisters. */ int fsdev_unmount_device(const char *name); /* also unregisters. */
int fsdev_register_keys(const char *name, unsigned int target_firmware, BisPartition part);
int fsdev_set_attr(const char *file, int attr, int mask); /* Non-standard function to set file DOS attributes. */ int fsdev_set_attr(const char *file, int attr, int mask); /* Non-standard function to set file DOS attributes. */
int fsdev_get_attr(const char *file); /* Non-standard function to get file DOS attributes. */ int fsdev_get_attr(const char *file); /* Non-standard function to get file DOS attributes. */

View file

@ -13,10 +13,12 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#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;
@ -54,7 +56,7 @@ bool is_valid_folder(const char *path) {
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
return true; return true;
} }
return false; return false;
} }
@ -63,6 +65,29 @@ bool is_valid_file(const char *path) {
if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
return true; return true;
} }
return false; return false;
} }
bool is_valid_concatenation_file(const char *path) {
if (is_valid_file(path)) {
return true;
} else if (is_valid_folder(path)) {
/* Check if the archive bit is set. */
int rc = fsdev_get_attr(path);
/* Failed to get file DOS attributes. */
if (rc == -1) {
return false;
}
/* Check if our path is not a directory (it should be if we're in this code, though...). */
if (!(rc & AM_DIR)) {
return false;
}
return (rc & AM_ARC) != 0;
} else {
return false;
}
}

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FUSEE_FS_UTILS_H #ifndef FUSEE_FS_UTILS_H
#define FUSEE_FS_UTILS_H #define FUSEE_FS_UTILS_H
@ -25,4 +25,6 @@ size_t dump_to_file(const void *src, size_t src_size, const char *filename);
bool is_valid_folder(const char *path); bool is_valid_folder(const char *path);
bool is_valid_file(const char *path); bool is_valid_file(const char *path);
bool is_valid_concatenation_file(const char *path);
#endif #endif

View file

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

View file

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

View file

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

View file

@ -91,7 +91,7 @@ static void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *b
/** /**
* print - logs a message and prints it to screen based on its screen_log_level * print - logs a message and prints it to screen based on its screen_log_level
* *
* If the level is below g_screen_log_level it will not be shown but logged to UART * If the level is below g_screen_log_level it will not be shown but logged to UART
* Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added * Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added
* UART is TODO * UART is TODO

View file

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

View file

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

View file

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FUSEE_NX_BOOT_H #ifndef FUSEE_NX_BOOT_H
#define FUSEE_NX_BOOT_H #define FUSEE_NX_BOOT_H
@ -35,7 +35,7 @@ typedef struct {
#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00 #define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00
#define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000 #define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620)) #define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620))
#define MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + n) #define MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + n)
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10) #define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10)

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h> #include <string.h>
#include "cluster.h" #include "cluster.h"
@ -30,40 +30,40 @@
void nxboot_finish(uint32_t boot_memaddr) { void nxboot_finish(uint32_t boot_memaddr) {
uint32_t target_firmware = MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware; uint32_t target_firmware = MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware;
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
/* Clear used keyslots. */ /* Clear used keyslots. */
clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY);
clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY);
/* 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);
} }
/* Finalize the GPU UCODE carveout. */ /* Finalize the GPU UCODE carveout. */
/* NOTE: [4.0.0+] This is now done in the Secure Monitor. */ /* NOTE: [4.0.0+] This is now done in the Secure Monitor. */
/* mc_config_carveout_finalize(); */ /* mc_config_carveout_finalize(); */
/* Lock AES keyslots. */ /* Lock AES keyslots. */
for (uint32_t i = 0; i < 16; i++) for (uint32_t i = 0; i < 16; i++)
set_aes_keyslot_flags(i, 0x15); set_aes_keyslot_flags(i, 0x15);
/* Lock RSA keyslots. */ /* Lock RSA keyslots. */
for (uint32_t i = 0; i < 2; i++) for (uint32_t i = 0; i < 2; i++)
set_rsa_keyslot_flags(i, 1); set_rsa_keyslot_flags(i, 1);
/* Lock the Security Engine. */ /* Lock the Security Engine. */
se->SE_TZRAM_SECURITY = 0; se->SE_TZRAM_SECURITY = 0;
se->SE_CRYPTO_SECURITY_PERKEY = 0; se->SE_CRYPTO_SECURITY_PERKEY = 0;
se->SE_RSA_SECURITY_PERKEY = 0; se->SE_RSA_SECURITY_PERKEY = 0;
se->SE_SE_SECURITY &= 0xFFFFFFFB; se->SE_SE_SECURITY &= 0xFFFFFFFB;
/* 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;
@ -71,30 +71,30 @@ void nxboot_finish(uint32_t boot_memaddr) {
/* Terminate the display. */ /* Terminate the display. */
display_end(); display_end();
/* Check if SMMU emulation has been used. */ /* Check if SMMU emulation has been used. */
uint32_t smmu_magic = *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC); uint32_t smmu_magic = *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC);
if (smmu_magic == 0xDEADC0DE) { if (smmu_magic == 0xDEADC0DE) {
/* Clear the magic. */ /* Clear the magic. */
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0; *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0;
/* Pass the boot address to the already running payload. */ /* Pass the boot address to the already running payload. */
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xF0) = boot_memaddr; *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xF0) = boot_memaddr;
/* Wait a while. */ /* Wait a while. */
mdelay(500); mdelay(500);
} else { } else {
/* Boot CPU0. */ /* Boot CPU0. */
cluster_boot_cpu0(boot_memaddr); cluster_boot_cpu0(boot_memaddr);
} }
/* Wait for Exosphère to wake up. */ /* Wait for Exosphère to wake up. */
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) == 0) { while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) == 0) {
udelay(1); udelay(1);
} }
/* Signal Exosphère. */ /* Signal Exosphère. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED; MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED;
} else { } else {
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED_4X; MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED_4X;

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
@ -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;
@ -59,7 +61,7 @@ SdmmcPartitionNum g_current_emmc_partition = SDMMC_PARTITION_INVALID;
static int mmc_partition_initialize(device_partition_t *devpart) { static int mmc_partition_initialize(device_partition_t *devpart) {
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct; mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
/* Allocate the crypto work buffer. */ /* Allocate the crypto work buffer. */
if ((devpart->read_cipher != NULL) || (devpart->write_cipher != NULL)) { if ((devpart->read_cipher != NULL) || (devpart->write_cipher != NULL)) {
devpart->crypto_work_buffer = memalign(16, devpart->sector_size * 16); devpart->crypto_work_buffer = memalign(16, devpart->sector_size * 16);
@ -105,7 +107,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
static void mmc_partition_finalize(device_partition_t *devpart) { static void mmc_partition_finalize(device_partition_t *devpart) {
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct; mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
/* Finalize hardware. */ /* Finalize hardware. */
if (mmcpart->device == &g_sd_device) { if (mmcpart->device == &g_sd_device) {
if (g_is_emummc) { if (g_is_emummc) {
@ -123,13 +125,13 @@ static void mmc_partition_finalize(device_partition_t *devpart) {
} }
devpart->initialized = false; devpart->initialized = false;
} }
/* Disable AHB redirection if necessary. */ /* Disable AHB redirection if necessary. */
if (g_ahb_redirect_enabled) { if (g_ahb_redirect_enabled) {
mc_disable_ahb_redirect(); mc_disable_ahb_redirect();
g_ahb_redirect_enabled = false; g_ahb_redirect_enabled = false;
} }
/* Free the crypto work buffer. */ /* Free the crypto work buffer. */
if (devpart->crypto_work_buffer != NULL) { if (devpart->crypto_work_buffer != NULL) {
free(devpart->crypto_work_buffer); free(devpart->crypto_work_buffer);
@ -138,19 +140,19 @@ static void mmc_partition_finalize(device_partition_t *devpart) {
static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) { static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct; mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) { if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) {
if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition)) if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition))
return EIO; return EIO;
g_current_emmc_partition = mmcpart->partition; g_current_emmc_partition = mmcpart->partition;
} }
return sdmmc_device_read(mmcpart->device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, dst) ? 0 : EIO; return sdmmc_device_read(mmcpart->device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, dst) ? 0 : EIO;
} }
static int mmc_partition_write(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) { static int mmc_partition_write(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) {
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct; mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) { if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) {
if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition)) if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition))
return EIO; return EIO;
@ -174,11 +176,11 @@ static int emummc_partition_initialize(device_partition_t *devpart) {
devpart->crypto_work_buffer_num_sectors = 0; devpart->crypto_work_buffer_num_sectors = 0;
} }
devpart->initialized = true; devpart->initialized = true;
return 0; return 0;
} }
static void emummc_partition_finalize(device_partition_t *devpart) { static void emummc_partition_finalize(device_partition_t *devpart) {
/* Free the crypto work buffer. */ /* Free the crypto work buffer. */
if (devpart->crypto_work_buffer != NULL) { if (devpart->crypto_work_buffer != NULL) {
free(devpart->crypto_work_buffer); free(devpart->crypto_work_buffer);
@ -194,10 +196,10 @@ static int emummc_partition_read(device_partition_t *devpart, void *dst, uint64_
rc = (fread(dst, devpart->sector_size, num_sectors, emummc_file) > 0) ? 0 : -1; rc = (fread(dst, devpart->sector_size, num_sectors, emummc_file) > 0) ? 0 : -1;
fclose(emummc_file); fclose(emummc_file);
return rc; return rc;
} else { } else {
/* Read partition data directly from the SD card device. */ /* Read partition data directly from the SD card device. */
return sdmmc_device_read(&g_sd_device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, dst) ? 0 : EIO; return sdmmc_device_read(&g_sd_device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, dst) ? 0 : EIO;
} }
} }
static int emummc_partition_write(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) { static int emummc_partition_write(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) {
@ -212,7 +214,7 @@ static int emummc_partition_write(device_partition_t *devpart, const void *src,
} else { } else {
/* Write partition data directly to the SD card device. */ /* Write partition data directly to the SD card device. */
return sdmmc_device_write(&g_sd_device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, (void *)src) ? 0 : EIO; return sdmmc_device_write(&g_sd_device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, (void *)src) ? 0 : EIO;
} }
} }
static int nxfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) { static int nxfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) {
@ -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},
}; };
@ -442,26 +446,26 @@ int nxfs_mount_sd() {
model.device_struct = &g_sd_mmcpart; model.device_struct = &g_sd_mmcpart;
model.start_sector = 0; model.start_sector = 0;
model.num_sectors = 1u << 30; /* arbitrary numbers of sectors. TODO: find the size of the SD in sectors. */ model.num_sectors = 1u << 30; /* arbitrary numbers of sectors. TODO: find the size of the SD in sectors. */
/* Mount the SD card device. */ /* Mount the SD card device. */
rc = fsdev_mount_device("sdmc", &model, true); rc = fsdev_mount_device("sdmc", &model, true);
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* Register the SD card device. */ /* Register the SD card device. */
rc = fsdev_register_device("sdmc"); rc = fsdev_register_device("sdmc");
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* All fs devices are ready. */ /* All fs devices are ready. */
if (rc == 0) { if (rc == 0) {
g_fsdev_ready = true; g_fsdev_ready = true;
} }
return rc; return rc;
} }
@ -469,36 +473,36 @@ int nxfs_mount_emmc() {
device_partition_t model; device_partition_t model;
int rc; int rc;
FILE *rawnand; FILE *rawnand;
/* Setup a template for boot0. */ /* Setup a template for boot0. */
model = g_mmc_devpart_template; model = g_mmc_devpart_template;
model.device_struct = &g_emmc_boot0_mmcpart; model.device_struct = &g_emmc_boot0_mmcpart;
model.start_sector = 0; model.start_sector = 0;
model.num_sectors = 0x184000 / model.sector_size; model.num_sectors = 0x184000 / model.sector_size;
/* Mount boot0 device. */ /* Mount boot0 device. */
rc = rawdev_mount_device("boot0", &model, true); rc = rawdev_mount_device("boot0", &model, true);
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* Register boot0 device. */ /* Register boot0 device. */
rc = rawdev_register_device("boot0"); rc = rawdev_register_device("boot0");
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* Setup a template for boot1. */ /* Setup a template for boot1. */
model = g_mmc_devpart_template; model = g_mmc_devpart_template;
model.device_struct = &g_emmc_boot1_mmcpart; model.device_struct = &g_emmc_boot1_mmcpart;
model.start_sector = 0; model.start_sector = 0;
model.num_sectors = 0x80000 / model.sector_size; model.num_sectors = 0x80000 / model.sector_size;
/* Mount boot1 device. */ /* Mount boot1 device. */
rc = rawdev_mount_device("boot1", &model, false); rc = rawdev_mount_device("boot1", &model, false);
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
@ -510,38 +514,38 @@ int nxfs_mount_emmc() {
model.device_struct = &g_emmc_user_mmcpart; model.device_struct = &g_emmc_user_mmcpart;
model.start_sector = 0; model.start_sector = 0;
model.num_sectors = (256ull << 30) / model.sector_size; model.num_sectors = (256ull << 30) / model.sector_size;
/* Mount raw NAND device. */ /* Mount raw NAND device. */
rc = rawdev_mount_device("rawnand", &model, false); rc = rawdev_mount_device("rawnand", &model, false);
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* Register raw NAND device. */ /* Register raw NAND device. */
rc = rawdev_register_device("rawnand"); rc = rawdev_register_device("rawnand");
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* Open raw NAND device. */ /* Open raw NAND device. */
rawnand = fopen("rawnand:/", "rb"); rawnand = fopen("rawnand:/", "rb");
if (rawnand == NULL) { if (rawnand == NULL) {
return -1; return -1;
} }
/* Iterate the GPT and mount each raw NAND partition. */ /* Iterate the GPT and mount each raw NAND partition. */
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
/* Close raw NAND device. */ /* Close raw NAND device. */
fclose(rawnand); fclose(rawnand);
/* All raw devices are ready. */ /* All raw devices are ready. */
if (rc == 0) { if (rc == 0) {
g_rawdev_ready = true; g_rawdev_ready = true;
} }
return rc; return rc;
} }
@ -549,7 +553,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
device_partition_t model; device_partition_t model;
int rc; int rc;
FILE *rawnand; FILE *rawnand;
/* Setup an emulation template for boot0. */ /* Setup an emulation template for boot0. */
model = g_emummc_devpart_template; model = g_emummc_devpart_template;
model.start_sector = emummc_start_sector + (0x400000 * 0 / model.sector_size); model.start_sector = emummc_start_sector + (0x400000 * 0 / model.sector_size);
@ -558,20 +562,20 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
/* Mount emulated boot0 device. */ /* Mount emulated boot0 device. */
rc = emudev_mount_device("boot0", &model, NULL, 0, 0); rc = emudev_mount_device("boot0", &model, NULL, 0, 0);
/* Failed to mount boot0 device. */ /* Failed to mount boot0 device. */
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* Register emulated boot0 device. */ /* Register emulated boot0 device. */
rc = emudev_register_device("boot0"); rc = emudev_register_device("boot0");
/* Failed to register boot0 device. */ /* Failed to register boot0 device. */
if (rc == -1) { if (rc == -1) {
return -2; return -2;
} }
/* Setup an emulation template for boot1. */ /* Setup an emulation template for boot1. */
model = g_emummc_devpart_template; model = g_emummc_devpart_template;
model.start_sector = emummc_start_sector + (0x400000 * 1 / model.sector_size); model.start_sector = emummc_start_sector + (0x400000 * 1 / model.sector_size);
@ -580,7 +584,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
/* Mount emulated boot1 device. */ /* Mount emulated boot1 device. */
rc = emudev_mount_device("boot1", &model, NULL, 0, 0); rc = emudev_mount_device("boot1", &model, NULL, 0, 0);
/* Failed to mount boot1. */ /* Failed to mount boot1. */
if (rc == -1) { if (rc == -1) {
return -3; return -3;
@ -593,43 +597,43 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
model.start_sector = emummc_start_sector + (0x400000 * 2 / model.sector_size); model.start_sector = emummc_start_sector + (0x400000 * 2 / model.sector_size);
model.num_sectors = (256ull << 30) / model.sector_size; model.num_sectors = (256ull << 30) / model.sector_size;
model.emu_use_file = false; model.emu_use_file = false;
/* Mount emulated raw NAND device. */ /* Mount emulated raw NAND device. */
rc = emudev_mount_device("rawnand", &model, NULL, 0, 0); rc = emudev_mount_device("rawnand", &model, NULL, 0, 0);
/* Failed to mount raw NAND. */ /* Failed to mount raw NAND. */
if (rc == -1) { if (rc == -1) {
return -4; return -4;
} }
/* Register emulated raw NAND device. */ /* Register emulated raw NAND device. */
rc = emudev_register_device("rawnand"); rc = emudev_register_device("rawnand");
/* Failed to register raw NAND device. */ /* Failed to register raw NAND device. */
if (rc == -1) { if (rc == -1) {
return -5; return -5;
} }
/* Open emulated raw NAND device. */ /* Open emulated raw NAND device. */
rawnand = fopen("rawnand:/", "rb"); rawnand = fopen("rawnand:/", "rb");
/* Failed to open emulated raw NAND device. */ /* Failed to open emulated raw NAND device. */
if (rawnand == NULL) { if (rawnand == NULL) {
return -6; return -6;
} }
/* Iterate the GPT and mount each emulated raw NAND partition. */ /* Iterate the GPT and mount each emulated raw NAND partition. */
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, NULL, 0, 0); rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, NULL, 0, 0);
/* Close emulated raw NAND device. */ /* Close emulated raw NAND device. */
fclose(rawnand); fclose(rawnand);
/* All emulated devices are ready. */ /* All emulated devices are ready. */
if (rc == 0) { if (rc == 0) {
g_emudev_ready = true; g_emudev_ready = true;
g_is_emummc = true; g_is_emummc = true;
} }
return rc; return rc;
} }
@ -640,85 +644,85 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
bool is_exfat; bool is_exfat;
char emummc_boot0_path[0x300 + 1] = {0}; char emummc_boot0_path[0x300 + 1] = {0};
char emummc_boot1_path[0x300 + 1] = {0}; char emummc_boot1_path[0x300 + 1] = {0};
/* Check if the SD card is EXFAT formatted. */ /* Check if the SD card is EXFAT formatted. */
rc = fsdev_is_exfat("sdmc"); rc = fsdev_is_exfat("sdmc");
/* Failed to detect file system type. */ /* Failed to detect file system type. */
if (rc == -1) { if (rc == -1) {
return -1; return -1;
} }
/* Set EXFAT status. */ /* Set EXFAT status. */
is_exfat = (rc == 1); is_exfat = (rc == 1);
/* Reject single part in FAT32. */ /* Reject single part in FAT32. */
/* NOTE: This check has no effect in the current design. */ /* NOTE: This check has no effect in the current design. */
if (!is_exfat && (num_parts < 1)) { if (!is_exfat && (num_parts < 1)) {
return -2; return -2;
} }
/* We want a folder with the archive bit set. */ /* We want a folder with the archive bit set. */
rc = fsdev_get_attr(emummc_path); rc = fsdev_get_attr(emummc_path);
/* Failed to get file DOS attributes. */ /* Failed to get file DOS attributes. */
if (rc == -1) { if (rc == -1) {
return -3; return -3;
} }
/* Our path is not a directory. */ /* Our path is not a directory. */
if (!(rc & AM_DIR)) { if (!(rc & AM_DIR)) {
return -4; return -4;
} }
/* Check if the archive bit is not set. */ /* Check if the archive bit is not set. */
if (!(rc & AM_ARC)) { if (!(rc & AM_ARC)) {
/* Try to set the archive bit. */ /* Try to set the archive bit. */
rc = fsdev_set_attr(emummc_path, AM_ARC, AM_ARC); rc = fsdev_set_attr(emummc_path, AM_ARC, AM_ARC);
/* Failed to set file DOS attributes. */ /* Failed to set file DOS attributes. */
if (rc == -1) { if (rc == -1) {
return -5; return -5;
} }
} }
/* Setup an emulation template for boot0. */ /* Setup an emulation template for boot0. */
model = g_emummc_devpart_template; model = g_emummc_devpart_template;
model.start_sector = 0; model.start_sector = 0;
model.num_sectors = 0x400000 / model.sector_size; model.num_sectors = 0x400000 / model.sector_size;
model.emu_use_file = true; model.emu_use_file = true;
/* Prepare boot0 file path. */ /* Prepare boot0 file path. */
snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0"); snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0");
/* Mount emulated boot0 device. */ /* Mount emulated boot0 device. */
rc = emudev_mount_device("boot0", &model, emummc_boot0_path, 0, 0); rc = emudev_mount_device("boot0", &model, emummc_boot0_path, 0, 0);
/* Failed to mount boot0 device. */ /* Failed to mount boot0 device. */
if (rc == -1) { if (rc == -1) {
return -6; return -6;
} }
/* Register emulated boot0 device. */ /* Register emulated boot0 device. */
rc = emudev_register_device("boot0"); rc = emudev_register_device("boot0");
/* Failed to register boot0 device. */ /* Failed to register boot0 device. */
if (rc == -1) { if (rc == -1) {
return -7; return -7;
} }
/* Setup an emulation template for boot1. */ /* Setup an emulation template for boot1. */
model = g_emummc_devpart_template; model = g_emummc_devpart_template;
model.start_sector = 0; model.start_sector = 0;
model.num_sectors = 0x400000 / model.sector_size; model.num_sectors = 0x400000 / model.sector_size;
model.emu_use_file = true; model.emu_use_file = true;
/* Prepare boot1 file path. */ /* Prepare boot1 file path. */
snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1"); snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1");
/* Mount emulated boot1 device. */ /* Mount emulated boot1 device. */
rc = emudev_mount_device("boot1", &model, emummc_boot1_path, 0, 0); rc = emudev_mount_device("boot1", &model, emummc_boot1_path, 0, 0);
/* Failed to mount boot1. */ /* Failed to mount boot1. */
if (rc == -1) { if (rc == -1) {
return -8; return -8;
@ -726,7 +730,7 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Register emulated boot1 device. */ /* Register emulated boot1 device. */
rc = emudev_register_device("boot1"); rc = emudev_register_device("boot1");
/* Failed to register boot1 device. */ /* Failed to register boot1 device. */
if (rc == -1) { if (rc == -1) {
return -9; return -9;
@ -737,93 +741,93 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
model.start_sector = 0; model.start_sector = 0;
model.num_sectors = (256ull << 30) / model.sector_size; model.num_sectors = (256ull << 30) / model.sector_size;
model.emu_use_file = true; model.emu_use_file = true;
/* Mount emulated raw NAND device from single or multiple parts. */ /* Mount emulated raw NAND device from single or multiple parts. */
rc = emudev_mount_device("rawnand", &model, emummc_path, num_parts, part_limit); rc = emudev_mount_device("rawnand", &model, emummc_path, num_parts, part_limit);
/* Failed to mount raw NAND. */ /* Failed to mount raw NAND. */
if (rc == -1) { if (rc == -1) {
return -10; return -10;
} }
/* Register emulated raw NAND device. */ /* Register emulated raw NAND device. */
rc = emudev_register_device("rawnand"); rc = emudev_register_device("rawnand");
/* Failed to register raw NAND device. */ /* Failed to register raw NAND device. */
if (rc == -1) { if (rc == -1) {
return -11; return -11;
} }
/* Open emulated raw NAND device. */ /* Open emulated raw NAND device. */
rawnand = fopen("rawnand:/", "rb"); rawnand = fopen("rawnand:/", "rb");
/* Failed to open emulated raw NAND device. */ /* Failed to open emulated raw NAND device. */
if (rawnand == NULL) { if (rawnand == NULL) {
return -12; return -12;
} }
/* Iterate the GPT and mount each emulated raw NAND partition. */ /* Iterate the GPT and mount each emulated raw NAND partition. */
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, emummc_path, num_parts, part_limit); rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, emummc_path, num_parts, part_limit);
/* Close emulated raw NAND device. */ /* Close emulated raw NAND device. */
fclose(rawnand); fclose(rawnand);
/* All emulated devices are ready. */ /* All emulated devices are ready. */
if (rc == 0) { if (rc == 0) {
g_emudev_ready = true; g_emudev_ready = true;
g_is_emummc = true; g_is_emummc = true;
} }
return rc; return rc;
} }
int nxfs_unmount_sd() { int nxfs_unmount_sd() {
int rc = 0; int rc = 0;
/* Unmount all fs devices. */ /* Unmount all fs devices. */
if (g_fsdev_ready) { if (g_fsdev_ready) {
rc = fsdev_unmount_all(); rc = fsdev_unmount_all();
g_fsdev_ready = false; g_fsdev_ready = false;
} }
return rc; return rc;
} }
int nxfs_unmount_emmc() { int nxfs_unmount_emmc() {
int rc = 0; int rc = 0;
/* Unmount all raw devices. */ /* Unmount all raw devices. */
if (g_rawdev_ready) { if (g_rawdev_ready) {
rc = rawdev_unmount_all(); rc = rawdev_unmount_all();
g_rawdev_ready = false; g_rawdev_ready = false;
} }
return rc; return rc;
} }
int nxfs_unmount_emummc() { int nxfs_unmount_emummc() {
int rc = 0; int rc = 0;
/* Unmount all emulated devices. */ /* Unmount all emulated devices. */
if (g_emudev_ready) { if (g_emudev_ready) {
rc = emudev_unmount_all(); rc = emudev_unmount_all();
g_emudev_ready = false; g_emudev_ready = false;
} }
return rc; return rc;
} }
int nxfs_init() { int nxfs_init() {
int rc; int rc;
/* Mount and register the SD card. */ /* Mount and register the SD card. */
rc = nxfs_mount_sd(); rc = nxfs_mount_sd();
/* Set the SD card as the default file system device. */ /* Set the SD card as the default file system device. */
if (rc == 0) { if (rc == 0) {
rc = fsdev_set_default_device("sdmc"); rc = fsdev_set_default_device("sdmc");
} }
return rc; return rc;
} }

View file

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

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h> #include <string.h>
#include "utils.h" #include "utils.h"
@ -60,7 +60,7 @@ void se_verify_flags_cleared(void) {
/* Set the flags for an AES keyslot. */ /* Set the flags for an AES keyslot. */
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic(); generic_panic();
} }
@ -79,7 +79,7 @@ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
/* Set the flags for an RSA keyslot. */ /* Set the flags for an RSA keyslot. */
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX) { if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic(); generic_panic();
} }
@ -98,7 +98,7 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
void clear_aes_keyslot(unsigned int keyslot) { void clear_aes_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic(); generic_panic();
} }
@ -112,7 +112,7 @@ void clear_aes_keyslot(unsigned int keyslot) {
void clear_rsa_keyslot(unsigned int keyslot) { void clear_rsa_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX) { if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic(); generic_panic();
} }
@ -132,7 +132,7 @@ void clear_rsa_keyslot(unsigned int keyslot) {
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) {
generic_panic(); generic_panic();
} }
@ -145,7 +145,7 @@ void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) {
generic_panic(); generic_panic();
} }
@ -166,7 +166,7 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) {
generic_panic(); generic_panic();
} }
@ -179,7 +179,7 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
void clear_aes_keyslot_iv(unsigned int keyslot) { void clear_aes_keyslot_iv(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic(); generic_panic();
} }
@ -198,7 +198,7 @@ void set_se_ctr(const void *ctr) {
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) {
generic_panic(); generic_panic();
} }
@ -235,7 +235,7 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co
void se_get_exp_mod_output(void *buf, size_t size) { void se_get_exp_mod_output(void *buf, size_t size) {
size_t num_dwords = (size >> 2); size_t num_dwords = (size >> 2);
if (num_dwords < 1) { if (num_dwords < 1) {
return; return;
} }
@ -351,7 +351,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) {
generic_panic(); generic_panic();
} }
@ -382,7 +382,7 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
generic_panic(); generic_panic();
} }
@ -403,7 +403,7 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
generic_panic(); generic_panic();
} }
@ -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,16 +470,16 @@ 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) {
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY); se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
@ -480,38 +490,39 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys
} }
se->SE_CRYPTO_LAST_BLOCK = (size >> 4) - 1; se->SE_CRYPTO_LAST_BLOCK = (size >> 4) - 1;
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++;
} }
} }
void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic(); generic_panic();
} }
@ -568,7 +579,7 @@ void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size,
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) { void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
generic_panic(); generic_panic();
} }
@ -583,7 +594,7 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
/* SHA256 Implementation. */ /* SHA256 Implementation. */
void se_calculate_sha256(void *dst, const void *src, size_t src_size) { void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
/* Setup config for SHA256, size = BITS(src_size) */ /* Setup config for SHA256, size = BITS(src_size) */
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
se->SE_SHA_CONFIG = 1; se->SE_SHA_CONFIG = 1;
@ -608,7 +619,7 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
/* RNG API */ /* RNG API */
void se_initialize_rng(unsigned int keyslot) { void se_initialize_rng(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic(); generic_panic();
} }
@ -628,7 +639,7 @@ void se_initialize_rng(unsigned int keyslot) {
void se_generate_random(unsigned int keyslot, void *dst, size_t size) { void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
volatile tegra_se_t *se = se_get_regs(); volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic(); generic_panic();
} }

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FUSEE_SE_H #ifndef FUSEE_SE_H
#define FUSEE_SE_H #define FUSEE_SE_H
@ -182,8 +182,8 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size);
void set_se_ctr(const void *ctr); void set_se_ctr(const void *ctr);
/* Secure AES API */ /* Secure AES API */
void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size, unsigned int crypto_sector_size);
void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size, unsigned int crypto_sector_size);
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);

View file

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

View file

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

View file

@ -21,34 +21,18 @@
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>;
util::BitPack64 value; util::BitPack64 value;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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