diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index 2b3417629..d62775834 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -20,7 +20,9 @@ /* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ /* "XBC0" */ -#define MAGIC_EXOSPHERE_BOOTCONFIG (0x30434258) +#define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258) +/* "XBC1" */ +#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258) #define EXOSPHERE_TARGET_FIRMWARE_100 1 #define EXOSPHERE_TARGET_FIRMWARE_200 2 @@ -28,13 +30,18 @@ #define EXOSPHERE_TARGET_FIRMWARE_400 4 #define EXOSPHERE_TARGET_FIRMWARE_500 5 #define EXOSPHERE_TARGET_FIRMWARE_600 6 +#define EXOSPHERE_TARGET_FIRMWARE_620 7 #define EXOSPHERE_TARGET_FIRMWARE_MIN EXOSPHERE_TARGET_FIRMWARE_100 -#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_600 +#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_620 + +#define EXOSPHERE_FLAGS_DEFAULT 0x00000000 +#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) typedef struct { unsigned int magic; unsigned int target_firmware; + unsigned int flags; } exosphere_config_t; #define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index e67d3dfbd..825bc9d3e 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -56,7 +56,7 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = { static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t tsec_key_id) { - return tsec_get_key(dst, tsec_key_id, tsec_fw); + return tsec_get_key(dst, tsec_key_id, tsec_fw, tsec_fw_size); } static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) { @@ -125,9 +125,10 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui set_aes_keyslot_flags(0xD, 0x15); /* Set TSEC key. */ - if (get_tsec_key(work_buffer, tsec_fw, tsec_fw_size, 1) != 0) { + if (get_tsec_key(work_buffer, tsec_fw, tsec_fw_size, 1) != 0) { return -1; } + set_aes_keyslot(0xD, work_buffer, 0x10); /* Decrypt all keyblobs, setting keyslot 0xF correctly. */ diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 9b9c73ed2..0380b3544 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -76,8 +76,15 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { return EXOSPHERE_TARGET_FIRMWARE_400; case 0x0B: /* 5.0.0 - 5.1.0 */ return EXOSPHERE_TARGET_FIRMWARE_500; - case 0x0E: /* 6.0.0 */ - return EXOSPHERE_TARGET_FIRMWARE_600; + case 0x0E: { /* 6.0.0 - 6.2.0 */ + if (memcmp(package1loader_header->build_timestamp, "20180802", 8) == 0) { + return EXOSPHERE_TARGET_FIRMWARE_600; + } else if (memcmp(package1loader_header->build_timestamp, "20181107", 8) == 0) { + return EXOSPHERE_TARGET_FIRMWARE_620; + } else { + fatal_error("[NXBOOT]: Unable to identify package1!\n"); + } + } default: return 0; } @@ -88,6 +95,7 @@ static void nxboot_configure_exosphere(uint32_t target_firmware) { exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG; exo_cfg.target_firmware = target_firmware; + exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT; if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) { fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); @@ -260,11 +268,18 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); } fclose(boot0); + + /* Find the system's target firmware. */ + uint32_t target_firmware = nxboot_get_target_firmware(package1loader); + if (!target_firmware) + fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); + else + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware); /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); - if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00)) { + if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900)) { fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); @@ -280,19 +295,16 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } } else { - tsec_fw_size = package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size); - if (tsec_fw_size == 0) { + if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); } + if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + tsec_fw_size = 0x2900; + } else { + tsec_fw_size = 0xF00; + } } - /* Find the system's target firmware. */ - uint32_t target_firmware = nxboot_get_target_firmware(package1loader); - if (!target_firmware) - fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); - else - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware); - print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); /* Setup boot configuration for Exosphère. */ diff --git a/fusee/fusee-secondary/src/package1.c b/fusee/fusee-secondary/src/package1.c index 46ff14787..4f62310b6 100644 --- a/fusee/fusee-secondary/src/package1.c +++ b/fusee/fusee-secondary/src/package1.c @@ -90,15 +90,19 @@ int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_ return 0; } -size_t package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size) { +bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size) { /* The TSEC firmware is always located at a 256-byte aligned address. */ - /* We're looking for its 4 first bytes. We assume its size is always 0xF00 bytes. */ + /* We're looking for its 4 first bytes. */ const uint32_t *pos; uintptr_t pk1l = (uintptr_t)package1loader; - for (pos = (const uint32_t *)pk1l; (uintptr_t)pos < pk1l + package1loader_size && *pos != 0xCF42004D; pos += 0x40); - - (*tsec_fw) = (void *)pos; - return 0xF00; + for (pos = (const uint32_t *)pk1l; (uintptr_t)pos < pk1l + package1loader_size; pos += 0x40) { + if (*pos == 0xCF42004D) { + (*tsec_fw) = (void *)pos; + return true; + } + } + + return false; } size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size) { diff --git a/fusee/fusee-secondary/src/package1.h b/fusee/fusee-secondary/src/package1.h index 79bf25fbe..c20c88db4 100644 --- a/fusee/fusee-secondary/src/package1.h +++ b/fusee/fusee-secondary/src/package1.h @@ -46,7 +46,7 @@ typedef struct { int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0); -size_t package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size); +bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size); size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size); /* Must be aligned to 16 bytes. */ diff --git a/fusee/fusee-secondary/src/tsec.c b/fusee/fusee-secondary/src/tsec.c index f9cfeaa04..b864df405 100644 --- a/fusee/fusee-secondary/src/tsec.c +++ b/fusee/fusee-secondary/src/tsec.c @@ -49,7 +49,7 @@ static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t ph return tsec_dma_wait_idle(); } -int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw) +int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size) { volatile tegra_tsec_t *tsec = tsec_get_regs(); @@ -82,7 +82,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw) /* Load firmware. */ tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8; - for (uint32_t addr = 0; addr < 0xF00; addr += 0x100) + for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100) { if (!tsec_dma_phys_to_flcn(true, addr, addr)) { diff --git a/fusee/fusee-secondary/src/tsec.h b/fusee/fusee-secondary/src/tsec.h index 3ff537172..c16c2f9a3 100644 --- a/fusee/fusee-secondary/src/tsec.h +++ b/fusee/fusee-secondary/src/tsec.h @@ -109,6 +109,6 @@ static inline volatile tegra_tsec_t *tsec_get_regs(void) return (volatile tegra_tsec_t *)TSEC_BASE; } -int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw); +int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size); #endif \ No newline at end of file