mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 22:02:15 +00:00
fusee: retry tsec key generation on failure.
This commit is contained in:
parent
4827fd71b4
commit
0ef3368893
1 changed files with 64 additions and 39 deletions
|
@ -20,6 +20,8 @@
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "tsec.h"
|
#include "tsec.h"
|
||||||
|
|
||||||
|
#define TSEC_KEYGEN_MAX_RETRIES 25
|
||||||
|
|
||||||
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
|
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
|
||||||
|
|
||||||
static void safe_memcpy(void *dst, void *src, uint32_t sz) {
|
static void safe_memcpy(void *dst, void *src, uint32_t sz) {
|
||||||
|
@ -168,14 +170,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
/* Copy package1 into IRAM. */
|
/* Copy package1 into IRAM. */
|
||||||
memcpy((void *)0x40010000, package1, package1_size);
|
memcpy((void *)0x40010000, package1, package1_size);
|
||||||
|
|
||||||
/* Load the TSEC firmware from IRAM. */
|
|
||||||
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
|
|
||||||
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable the aperture since it has precedence over the SMMU. */
|
|
||||||
mc_disable_ahb_redirect();
|
|
||||||
|
|
||||||
/* Setup TSEC's address space. */
|
/* Setup TSEC's address space. */
|
||||||
uint32_t *pdir = smmu_setup_tsec_as(1);
|
uint32_t *pdir = smmu_setup_tsec_as(1);
|
||||||
|
|
||||||
|
@ -189,21 +183,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
volatile uint32_t *iram_pages = smmu_alloc_page(48);
|
volatile uint32_t *iram_pages = smmu_alloc_page(48);
|
||||||
volatile uint32_t *expv_page = smmu_alloc_page(1);
|
volatile uint32_t *expv_page = smmu_alloc_page(1);
|
||||||
|
|
||||||
/* Copy CAR, MC and FUSE. */
|
|
||||||
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
|
|
||||||
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
|
|
||||||
safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400);
|
|
||||||
|
|
||||||
/* Copy IRAM. */
|
|
||||||
memcpy((void *)iram_pages, (void *)0x40010000, 0x30000);
|
|
||||||
|
|
||||||
/* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */
|
|
||||||
car_page[0x1F4/4] = 2;
|
|
||||||
|
|
||||||
/* TSEC wants the aperture fully open. */
|
|
||||||
mc_page[0x65C/4] = 0;
|
|
||||||
mc_page[0x660/4] = 0x80000000;
|
|
||||||
|
|
||||||
/* Map all necessary pages. */
|
/* Map all necessary pages. */
|
||||||
smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||||
smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE);
|
smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE);
|
||||||
|
@ -217,20 +196,69 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
/* Enable the SMMU. */
|
/* Enable the SMMU. */
|
||||||
smmu_enable();
|
smmu_enable();
|
||||||
|
|
||||||
/* Run the TSEC firmware. */
|
/* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */
|
||||||
tsec_run_fw();
|
|
||||||
|
|
||||||
/* Extract the keys from SE. */
|
|
||||||
uint32_t key_buf[0x20/4] = {0};
|
uint32_t key_buf[0x20/4] = {0};
|
||||||
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
|
unsigned int retries = 0;
|
||||||
uint32_t old_key_data = *key_data;
|
while (true) {
|
||||||
uint32_t buf_counter = 0;
|
if (retries++ > TSEC_KEYGEN_MAX_RETRIES) {
|
||||||
while (!(tsec->FALCON_CPUCTL & 0x10)) {
|
fatal_error("[SMMU] TSEC key generation race was lost too many times!");
|
||||||
const uint32_t new_key_data = *key_data;
|
}
|
||||||
if (new_key_data != old_key_data) {
|
|
||||||
old_key_data = new_key_data;
|
/* Load the TSEC firmware from IRAM. */
|
||||||
key_buf[buf_counter] = new_key_data;
|
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
|
||||||
buf_counter++;
|
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable the aperture since it has precedence over the SMMU. */
|
||||||
|
mc_disable_ahb_redirect();
|
||||||
|
|
||||||
|
/* Clear all pages. */
|
||||||
|
memset((void *)car_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)fuse_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)pmc_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)flow_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)se_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)mc_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)iram_pages, 0, 48 * SMMU_PAGE_SIZE);
|
||||||
|
memset((void *)expv_page, 0, SMMU_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Copy CAR, MC and FUSE. */
|
||||||
|
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
|
||||||
|
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
|
||||||
|
safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400);
|
||||||
|
|
||||||
|
/* Copy IRAM. */
|
||||||
|
memcpy((void *)iram_pages, (void *)0x40010000, 0x30000);
|
||||||
|
|
||||||
|
/* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */
|
||||||
|
car_page[0x1F4/4] = 2;
|
||||||
|
|
||||||
|
/* TSEC wants the aperture fully open. */
|
||||||
|
mc_page[0x65C/4] = 0;
|
||||||
|
mc_page[0x660/4] = 0x80000000;
|
||||||
|
|
||||||
|
|
||||||
|
/* Run the TSEC firmware. */
|
||||||
|
tsec_run_fw();
|
||||||
|
|
||||||
|
/* Extract the keys from SE. */
|
||||||
|
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
|
||||||
|
uint32_t old_key_data = *key_data;
|
||||||
|
uint32_t buf_counter = 0;
|
||||||
|
while (!(tsec->FALCON_CPUCTL & 0x10)) {
|
||||||
|
const uint32_t new_key_data = *key_data;
|
||||||
|
if (new_key_data != old_key_data) {
|
||||||
|
old_key_data = new_key_data;
|
||||||
|
key_buf[buf_counter] = new_key_data;
|
||||||
|
buf_counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable back the aperture. */
|
||||||
|
mc_enable_ahb_redirect();
|
||||||
|
|
||||||
|
if (buf_counter == 8) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,9 +277,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||||
/* Clear TSEC's address space. */
|
/* Clear TSEC's address space. */
|
||||||
smmu_clear_tsec_as(1);
|
smmu_clear_tsec_as(1);
|
||||||
|
|
||||||
/* Enable back the aperture. */
|
|
||||||
mc_enable_ahb_redirect();
|
|
||||||
|
|
||||||
/* Return the decrypted package1 from emulated IRAM. */
|
/* Return the decrypted package1 from emulated IRAM. */
|
||||||
memcpy(package1_dec, (void *)iram_pages, package1_size);
|
memcpy(package1_dec, (void *)iram_pages, package1_size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue